当前位置: 首页 > news >正文

damn the jvm again(2)

都想看jvm是吧

class_monitor_agent.c

#include <jni.h>
#include <jvmti.h>
#include <stdio.h>
#include <string.h>// JVM TI环境指针
static jvmtiEnv* jvmti = NULL;// 类加载事件回调函数
void JNICALL ClassFileLoadHook(jvmtiEnv* jvmti, JNIEnv* jni,jclass class_being_redefined, jobject loader,const char* name, jobject protection_domain,jint class_data_len, const unsigned char* class_data,jint* new_class_data_len, unsigned char** new_class_data) {if (name != NULL) {printf("类加载: %s\n", name);} else {printf("类加载: 匿名类\n");}
}// 代理初始化函数 - 修正参数和调用方式
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {jint result;jvmtiCapabilities capabilities;jvmtiEventCallbacks callbacks;// 修正GetEnv调用参数和类型转换result = (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_2);if (result != JNI_OK || jvmti == NULL) {printf("无法获取JVM TI环境,错误码: %d\n", result);return JNI_ERR;}// 初始化能力结构体memset(&capabilities, 0, sizeof(capabilities));capabilities.can_retransform_classes = 1;// 修正能力字段名称capabilities.can_generate_all_class_hook_events = 1;// 设置能力result = (*jvmti)->AddCapabilities(jvmti, &capabilities);if (result != JVMTI_ERROR_NONE) {printf("无法设置JVM TI能力,错误码: %d\n", result);return JNI_ERR;}// 初始化回调结构体memset(&callbacks, 0, sizeof(callbacks));callbacks.ClassFileLoadHook = &ClassFileLoadHook;// 设置回调result = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));if (result != JVMTI_ERROR_NONE) {printf("无法设置JVM TI回调,错误码: %d\n", result);return JNI_ERR;}// 启用类加载事件监控result = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);if (result != JVMTI_ERROR_NONE) {printf("无法启用类加载事件,错误码: %d\n", result);return JNI_ERR;}printf("JVM TI代理初始化成功\n");return JNI_OK;
}// JVM退出时的处理
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM* vm) {if (jvmti != NULL) {// 禁用事件监控(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_DISABLE,JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);}printf("JVM TI代理卸载\n");
}

thread_trace_agent.c

#include <jni.h>
#include <jvmti.h>
#include <stdio.h>
#include <string.h>static jvmtiEnv* jvmti = NULL;// 线程启动回调
void JNICALL ThreadStart(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {// 尝试通过JNI获取线程名称(不依赖JVM TI特定能力)jclass thread_class = (*jni)->FindClass(jni, "java/lang/Thread");jmethodID get_name = (*jni)->GetMethodID(jni, thread_class, "getName", "()Ljava/lang/String;");jstring name_str = (jstring)(*jni)->CallObjectMethod(jni, thread, get_name);const char* name = name_str ? (*jni)->GetStringUTFChars(jni, name_str, NULL) : "无名线程";printf("[THREAD START] 名称: %s, 地址: %p\n", name, (void*)thread);// 释放资源if (name_str) {(*jni)->ReleaseStringUTFChars(jni, name_str, name);}
}// 线程结束回调
void JNICALL ThreadEnd(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {// 尝试通过JNI获取线程名称jclass thread_class = (*jni)->FindClass(jni, "java/lang/Thread");jmethodID get_name = (*jni)->GetMethodID(jni, thread_class, "getName", "()Ljava/lang/String;");jstring name_str = (jstring)(*jni)->CallObjectMethod(jni, thread, get_name);const char* name = name_str ? (*jni)->GetStringUTFChars(jni, name_str, NULL) : "无名线程";printf("[THREAD END] 名称: %s, 地址: %p\n", name, (void*)thread);// 释放资源if (name_str) {(*jni)->ReleaseStringUTFChars(jni, name_str, name);}
}// 代理初始化函数
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {jint result;jvmtiCapabilities capabilities;jvmtiEventCallbacks callbacks;// 获取JVM TI环境result = (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_2);if (result != JNI_OK || jvmti == NULL) {printf("无法获取JVM TI环境,错误码: %d\n", result);return JNI_ERR;}// 初始化能力结构体(移除Java SDK 24不支持的字段)memset(&capabilities, 0, sizeof(capabilities));// 注意:不设置can_get_thread_info和can_generate_thread_events(SDK 24无这些字段)// 尝试设置能力(忽略不支持字段导致的错误)result = (*jvmti)->AddCapabilities(jvmti, &capabilities);if (result != JVMTI_ERROR_NONE) {printf("警告: 能力设置部分失败,错误码: %d\n", result);}// 设置线程事件回调memset(&callbacks, 0, sizeof(callbacks));callbacks.ThreadStart = &ThreadStart;callbacks.ThreadEnd = &ThreadEnd;result = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));if (result != JVMTI_ERROR_NONE) {printf("无法设置回调,错误码: %d\n", result);return JNI_ERR;}// 启用线程启动事件result = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, NULL);if (result != JVMTI_ERROR_NONE) {printf("无法启用线程启动事件,错误码: %d\n", result);return JNI_ERR;}// 启用线程结束事件result = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_THREAD_END, NULL);if (result != JVMTI_ERROR_NONE) {printf("无法启用线程结束事件,错误码: %d\n", result);return JNI_ERR;}printf("线程跟踪代理初始化成功\n");return JNI_OK;
}// 代理卸载函数
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM* vm) {if (jvmti != NULL) {(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_DISABLE, JVMTI_EVENT_THREAD_START, NULL);(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_DISABLE, JVMTI_EVENT_THREAD_END, NULL);}
}

exception_trace_agent.c

#include <jni.h>
#include <jvmti.h>
#include <stdio.h>
#include <string.h>static jvmtiEnv* jvmti = NULL;// 异常捕获回调(适配Java SDK 24的事件类型)
void JNICALL ExceptionCatch(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jmethodID method, jlocation location, jthrowable exception) {jclass ex_class = (*jni)->GetObjectClass(jni, exception);char* ex_class_name;// 获取异常类名(*jvmti)->GetClassSignature(jvmti, ex_class, &ex_class_name, NULL);// 获取异常消息jmethodID get_message = (*jni)->GetMethodID(jni, ex_class, "getMessage", "()Ljava/lang/String;");jstring message_str = (jstring)(*jni)->CallObjectMethod(jni, exception, get_message);const char* message = message_str ? (*jni)->GetStringUTFChars(jni, message_str, NULL) : "无消息";printf("[EXCEPTION CAUGHT] 类型: %s, 消息: %s\n", ex_class_name, message);// 释放资源(*jvmti)->Deallocate(jvmti, (unsigned char*)ex_class_name);if (message_str) {(*jni)->ReleaseStringUTFChars(jni, message_str, message);}
}// 初始化代理
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {jint result;jvmtiCapabilities capabilities;jvmtiEventCallbacks callbacks;result = (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_2);if (result != JNI_OK || jvmti == NULL) return JNI_ERR;// 启用异常监控能力memset(&capabilities, 0, sizeof(capabilities));capabilities.can_generate_exception_events = 1;result = (*jvmti)->AddCapabilities(jvmti, &capabilities);if (result != JVMTI_ERROR_NONE) {printf("无法设置异常监控能力,错误码: %d\n", result);return JNI_ERR;}// 设置异常回调(使用ExceptionCatch而非ExceptionThrown)memset(&callbacks, 0, sizeof(callbacks));callbacks.ExceptionCatch = &ExceptionCatch;result = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));if (result != JVMTI_ERROR_NONE) return JNI_ERR;// 启用异常捕获事件(适配Java SDK 24)(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION_CATCH, NULL);printf("异常跟踪代理初始化成功\n");return JNI_OK;
}JNIEXPORT void JNICALL Agent_OnUnload(JavaVM* vm) {if (jvmti != NULL) {(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_DISABLE, JVMTI_EVENT_EXCEPTION_CATCH, NULL);}
}

object_trace_agent.c

#include <jni.h>
#include <jvmti.h>
#include <stdio.h>
#include <string.h>static jvmtiEnv* jvmti = NULL;// 对象分配事件回调
void JNICALL VMObjectAlloc(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread,jobject obj, jclass cls, jlong size) {char* class_name;// 获取类名(*jvmti)->GetClassSignature(jvmti, cls, &class_name, NULL);if (class_name) {printf("[ALLOC] 类: %s, 大小: %ld bytes\n", class_name, size);// 释放字符串(JVM TI分配的内存需手动释放)(*jvmti)->Deallocate(jvmti, (unsigned char*)class_name);}
}// 代理初始化
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {jint result;jvmtiCapabilities capabilities;jvmtiEventCallbacks callbacks;// 获取JVM TI环境result = (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_2);if (result != JNI_OK || jvmti == NULL) {printf("无法获取JVM TI环境\n");return JNI_ERR;}// 启用对象分配监控能力memset(&capabilities, 0, sizeof(capabilities));capabilities.can_generate_vm_object_alloc_events = 1;result = (*jvmti)->AddCapabilities(jvmti, &capabilities);if (result != JVMTI_ERROR_NONE) {printf("无法设置能力\n");return JNI_ERR;}// 设置回调memset(&callbacks, 0, sizeof(callbacks));callbacks.VMObjectAlloc = &VMObjectAlloc;result = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));if (result != JVMTI_ERROR_NONE) {printf("无法设置回调\n");return JNI_ERR;}// 启用对象分配事件result = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,JVMTI_EVENT_VM_OBJECT_ALLOC, NULL);if (result != JVMTI_ERROR_NONE) {printf("无法启用事件\n");return JNI_ERR;}printf("对象跟踪代理初始化成功\n");return JNI_OK;
}JNIEXPORT void JNICALL Agent_OnUnload(JavaVM* vm) {if (jvmti != NULL) {(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_DISABLE,JVMTI_EVENT_VM_OBJECT_ALLOC, NULL);}
}

gbuild.sh

# Usage: bash gbuild.sh what.c Jxxx.java
set -xeexport JAVA_INCLUDE_DIR=/etc/alternatives/java_sdk_24gcc -shared -fPIC -shared -I$JAVA_INCLUDE_DIR/include -I$JAVA_INCLUDE_DIR/include/linux $1 -o lib$1.sojava -agentpath:./lib$1.so $2

usage

bash gbuild.sh <what agent.c> <what test java>

JVMTITest.java

public class JVMTITest {// 内部类,用于展示更多类加载情况static class InnerClass {public void doSomething() {System.out.println("内部类方法被调用");}}public static void main(String[] args) {System.out.println("主程序开始运行");// 创建对象,触发类加载InnerClass inner = new InnerClass();inner.doSomething();// 尝试加载一个标准库类try {Class<?> stringClass = Class.forName("java.lang.String");System.out.println("加载了标准类: " + stringClass.getName());} catch (ClassNotFoundException e) {e.printStackTrace();}System.out.println("主程序运行结束");try {throw new Exception("damn");} catch (Exception e) {System.out.println(e.getMessage());}}
}

sample.log

  • https://gitee.com/EEPPEE_admin/jvm-backend-example/blob/jni-and-hack-jvm/hackjvm_example/sample.log
http://www.lryc.cn/news/618360.html

相关文章:

  • DDIA第五章:无主复制(去中心化复制)详解
  • 华为发布AI推理新技术,降低对HBM内存依赖
  • 阿里云国际DDoS高防:添加网站配置指南
  • LabVIEW菜单操控
  • 【USRP】基于LabVIEW的BPSK、QPSK,文本,图片
  • 区块链技术原理(7)-安全问题
  • C++少儿编程(二十二)—条件结构
  • 云原生作业(nginx)
  • QT(概述、基础函数、界面类、信号和槽)
  • Linux 服务器,安装mqtt服务
  • Linux 系统下 VS Code 降级至 1.85 版本教程:通过历史版本网站解决兼容性问题
  • 从零开始手搓一个GPT大语言模型:从理论到实践的完整指南(一)
  • Linux性能监控
  • Qt Charts 深度解析与实战指南
  • 全面解析MySQL(5)——“索引、事务、JDBC”三大核心
  • AI不再停留在概念阶段,而是在各行业核心业务场景产生实际价值。随着大模型、边缘计算等技术的突破,AI应用将向实时化、自主化、普惠化方向深度演进。
  • 高性能web服务器Tomcat
  • 飞算 JavaAI -智慧城市项目实践:从交通协同到应急响应的全链路技术革新
  • 有趣的 npm 库 · json-server
  • Qt之QMetaEnum的简单使用(含源码和注释)
  • Windows 命令行:打开命令提示符界面
  • 【DL】浅层神经网络
  • 【实时Linux实战系列】实时环境监测系统架构设计
  • Spring Boot 3 数据源连接信息存储方法
  • 蓝牙隐私保护机制:面试高频考点与真题解析
  • 多奥电梯智能化解决方案的深度解读与结构化总结,内容涵盖系统架构、功能模块、应用场景与社会价值四大维度,力求全面展示该方案的技术先进性与应用前景。
  • 线缆桥架、管道设计规范详解
  • C++中template、 implicit 、explicit关键字详解
  • Linux线程——对线程库简单的面向对象封装
  • KAQG:一种用于生成难度可控问题的知识图谱的增强的RAG系统(论文大白话)