JVMTI 笔记

JVMTI(JVM tool interface)是一套c/c++开发接口,用于对JVM进行性能分析、debug、内存管理、线程分析等各种黑科技操作

JVMTI开发1个CPU Profiler:

agent.c

复制代码
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
    jvmtiEnv *jvmti;
    (*vm)->GetEnv((void **)&jvmti, JVMTI_VERSION_1_0);
    // ...
    return JNI_OK;
}

开启一个线程定时循环执行如下操作:

// 获取所有线程的jthread jvmtiError GetAllThreads(jvmtiEnv *env, jint *threads_count_ptr, jthread **threads_ptr);

// 根据jthread获取该线程信息(name、daemon、priority...) jvmtiError GetThreadInfo(jvmtiEnv *env, jthread thread, jvmtiThreadInfo* info_ptr);

// 根据jthread获取该线程调用栈 jvmtiError GetStackTrace(jvmtiEnv *env, jthread thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo *frame_buffer, jint *count_ptr);

JVMTI开发1个Memory Profiler:

创建一个native工程,复制一份jdk中jvmti.h的头文件到项目cpp根目录(在jdk/include安装目录下)

自定义一个memory.cpp

复制代码
extern "C"
JNIEXPORT jint JNICALL
Agent_OnAttach(JavaVM *vm, char *options, void *reserved) {
    //准备JVMTI环境,初始化mJvmtiEnv
    vm->GetEnv((void **) &mJvmtiEnv, JVMTI_VERSION_1_2);
    return JNI_OK;
}

通过jvmtiEnv->SetEventCallbacks方法设定我们想要监听的事件到jvmtiEventCallbacks集合里

复制代码
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.VMObjectAlloc = &objectAlloc;
callbacks.ObjectFree = &objectFree;
//设置回调函数
mJvmtiEnv->SetEventCallbacks(&callbacks, sizeof(callbacks));

objectAlloc是监听内存申请函数,如果jvm执行内存分配事件,就会回调此函数,因此重写此函数的实现如下:

复制代码
void JNICALL objectAlloc(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread,
                         jobject object, jclass object_klass, jlong size) {
    jvmti_env->SetTag(object, tag);
    tag+= 1;
    char *classSignature;
    // 获取类签名
    jvmti_env->GetClassSignature(object_klass, &classSignature, nullptr);
    // 过滤条件
    if(strstr(classSignature, "com/test/memory") != nullptr){
        __android_log_print(ANDROID_LOG_ERROR, "hello", "%s",classSignature);
        myVM->AttachCurrentThread( &currentEnv, nullptr);
        // 这个list我们之后解释
        list.push_back(tag);
        char str[500];
        char *format = "%s: object alloc {Tag:%lld} \r\n";
        sprintf(str, format, classSignature,
                tag);
        memoryFile->write(str, sizeof(char) * strlen(str));
    }
    jvmti_env->Deallocate((unsigned char *) classSignature);
}

一个jvmti_env->SetTag的操作,这个是给这个分配的对象进行了一个打标签的动作(我们需要观察该对象是否被销毁,所以需要一个唯一标识符),我们会在释放的时候用到

objectFree是监听内存释放函数:

复制代码
void JNICALL objectFree(jvmtiEnv *jvmti_env,
                        jlong tag) {
    std::list<int>::iterator it = std::find(list1.begin(), list1.end(), tag);
    if (it != list.end()) // 找到了
    {
        __android_log_print(ANDROID_LOG_ERROR, "hello", "release %lld",tag);
        char str[500];
        char *format = "release tag %lld\r\n";
        //ALOGI(format, GetCurrentSystemTime().c_str(),threadInfo.name, classSignature, size, tag);
        sprintf(str, format,tag);
        memoryFile->write(str, sizeof(char) * strlen(str));
    }
}

记录内存分配信息:memoryFile->write(str, sizeof``(``char``) * strlen(str))

复制代码
void MemoryFile::write(char *data, int dataLen) {
    mtx.lock();
    if(currentSize + dataLen >= m_size){
        resize(currentSize+dataLen);
    }
    memcpy(ptr + currentSize, data, dataLen);
    currentSize += dataLen;
    mtx.unlock();
}

通过SetEventNotificationMode函数开启真正监听/关闭监听

复制代码
//开启监听
mJvmtiEnv->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, nullptr);
mJvmtiEnv->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_OBJECT_FREE, nullptr);

jvmtiError SetEventNotificationMode(jvmtiEventMode mode,
          jvmtiEvent event_type,
          jthread event_thread,
           ...) {
  return functions->SetEventNotificationMode(this, mode, event_type, event_thread);
}

参考:Android性能优化之JVMTI与内存分配_Android_脚本之家

相关推荐
一过菜只因5 小时前
MySql Jdbc
android·数据库·mysql
音视频牛哥7 小时前
Android音视频开发:基于 Camera2 API 实现RTMP推流、RTSP服务与录像一体化方案
android·音视频·安卓camera2推流·安卓camera2推送rtmp·安卓camera2 rtsp·安卓camera2录制mp4·安卓实现ipc摄像头
2501_937145417 小时前
2025 IPTV 源码优化版:稳定兼容 + 智能升级
android·源码·电视盒子·源代码管理·机顶盒
Nerve10 小时前
FluxImageLoader : 基于Coil3封装的 Android 图片加载库,旨在提供简单、高效且功能丰富的图片加载解决方案
android·android jetpack
元气满满-樱11 小时前
MySQL基础管理
android·mysql·adb
summerkissyou198711 小时前
android13-audio-AudioTrack-写数据流程
android·音视频
董三毛13 小时前
Kotlin Coroutine 底层实现原理
android
L1087013 小时前
AutoJsPro GoogleMaterial3 M3组件使用示例
android
枣把儿14 小时前
「zotepad」用Gemini3pro写出一个高效写作和发文的记事本应用
android·前端·nuxt.js
明川14 小时前
Android Gradle 学习 - 生命周期和Task
android·前端·gradle