JVMTI

** JVMTI**:它到底能干什么是怎么工作的,以及怎么使用它(尤其是在 Android 上的实际应用)。

一、JVMTI 到底是啥?为什么要用它?

JVMTI(Java Virtual Machine Tool Interface)是 Java 虚拟机提供的一套 原生接口(Native API),允许开发者编写 调试器、性能分析器、运行时监控工具 等低层次工具。它是 Java 平台中最强大、底层的调试接口之一。

在 Android 平台上,JVMTI 被广泛用于:

  • Android Studio 的 Layout Inspector
  • Memory Profiler
  • App Startup Profiler
  • 性能分析与热修复方案(如阿里 AndFix、腾讯 Matrix 等)

JVMTI 它不是写 App 用的,是给那些开发「调试器、性能分析工具、检测器、热修复系统」的人用的。

你可以把 JVMTI 想象成是:

JVM 的监听/操控台,可以用来偷偷观察、干预 Java 程序的运行过程。

比如你可以:

  • 偷偷记录谁创建了对象、什么时候销毁的;
  • 在某个方法开始前或结束后,插入自己的逻辑;
  • 修改类的定义、重新注入代码;
  • 看内存里有哪些对象,谁引用了它们;
  • 拦截异常抛出事件;
  • 检查是否有死锁或线程卡死。

二、JVMTI 能干什么?(详细功能+例子)

功能 能做什么 举例
类和方法信息 获取或修改类、方法的结构信息 获取类名、字段、方法签名;替换 class 定义
对象监控 追踪内存中对象的生命周期 哪个线程创建了它?被谁引用?
内存分析 获取堆栈快照、对象大小、引用链 做内存泄漏分析、堆视图
性能采样 定时查看当前调用栈 看应用卡顿在哪个函数
线程监控 线程创建、销毁、状态变化 看是否发生死锁
异常追踪 拦截异常抛出 统计某异常发生的频率
代码注入 动态替换类字节码(Redefine) 做热修复,不重启替换 class

三、工作原理简述(带图解)

+-----------------------+
|    Android Studio     |
| (或你的分析工具)       |
+-----------+-----------+
            |
        [加载 Agent]
            v
+-----------------------+
|     JVMTI Agent.so     |  ← 你写的 C/C++ 插件
+-----------+-----------+
            |
        [回调注册]
            v
+-----------------------+
|     ART / JVM         |  ← Android Runtime
+-----------------------+

步骤:

  1. 你编写一个 native 库(.so),这个库使用 JVMTI 提供的 C 接口。
  2. 在 App 启动时,这个库通过 -agentpath 或 Attach API 被加载到进程里。
  3. 你注册感兴趣的事件,比如“某个方法被调用”、“类被加载”。
  4. 当 JVM 发生这些事件,JVMTI 就会 回调你写的 native 函数
  5. 你可以获取数据、打印日志、甚至修改类结构。

总结来说就是:

  1. Android Studio 加载 JVMTI Agent 到目标进程
  2. Agent 注册回调方法,监听 JVM 事件
  3. ART Runtime 触发事件,调用 Agent 逻辑
  4. Agent 可以通过 JNI 操作 Java 层数据

在 Android 中的常用函数(C/C++)

jvmtiEnv* jvmti;
jvmti->SetEventNotificationMode(...);     // 开启某类事件通知
jvmti->GetLoadedClasses(...);             // 获取已加载类
jvmti->GetObjectSize(...);                // 获取对象大小
jvmti->RedefineClasses(...);              // 替换类定义

常用事件(JVMTI Event)

事件名 描述
JVMTI_EVENT_VM_INIT 虚拟机启动完成
JVMTI_EVENT_CLASS_LOAD 类加载
JVMTI_EVENT_METHOD_ENTRY 方法调用
JVMTI_EVENT_EXCEPTION 异常捕获
JVMTI_EVENT_GARBAGE_COLLECTION_START GC 开始
JVMTI_EVENT_OBJECT_FREE 对象回收

使用门槛

限制项 描述
Android 8.0+ Android 从 8.0(API 26)才开始支持 JVMTI
Native 实现 需要编写 .so 库,且具备 JNI 基础
Debuggable App 要调试的 App 通常需要是 debuggable 的
权限敏感 某些事件监控需要系统权限或 root

四、实际使用场景举例(以 Android 为主)

1. Android Studio 的 Layout Inspector

使用 JVMTI 遍历内存里的所有 Activity,找到当前显示的界面和 View 树(通过反射 Java 对象)。

2. Memory Profiler

通过 JVMTI 触发 堆快照,分析某个对象是否还被引用、大小是多少、谁持有引用。

3. 热修复(Redefine Classes)

比如你线上发布的 App 有 bug,可以用 JVMTI 把某个类在内存中的定义替换掉(如果类没有被 AOT 编译或内联)。

五、在 Android 上怎么使用 JVMTI?

1. 开启 JVMTI 支持(8.0+)

你必须在 Android 8.0(API 26)以上,且 App 是 debuggable=true。

2. 编写 agent(C/C++)

// agent.cpp
#include <jvmti.h>
#include <jni.h>

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
    jvmtiEnv* jvmti;
    vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_1);

    // 打开事件,比如类加载
    jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, nullptr);
    // 注册事件处理器...

    return JNI_OK;
}

你需要用 CMake 编译这个为 .so 库。

3. 启动时加载这个 Agent

你可以在 Android 中使用如下方式:

Debug.attachJvmtiAgent("/data/local/tmp/libagent.so", null, null);

注意:这个 API 需要 debuggable=true 和系统权限。

六、使用成本与限制

项目 说明
学习成本高 需要掌握 C/C++、JNI、JVM 内部结构
系统权限 有些能力需要 root 权限或系统签名 App
兼容性问题 Android 上部分 JVMTI 能力被限制(比如 Redefine 限制多)
性能开销 监控事件本身会带来开销,需谨慎使用

七、总结一句话

JVMTI 是 JVM/ART 的“监听钩子”,能让你动态观察、分析、甚至修改 Java 程序的运行行为,是开发调试器、Profiler、热修复系统的核心工具。

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器