JVM TI
JVM TI全名Java Virtual Machine Tool Interface,是开发虚拟机监控工具使用的编程接口,它可以监控JVM内部时间的执行,也可以控制JVM的某些行为,可以实现调试、监控、线程分析、覆盖率分析工具等
JVM TI属于Java Platform Debugger Architecyure中的一员,在Debugger Architecture上JVM TI可以算是一个back-end,通过JDWP和front-end JDI去做交互,需要注意的是Android内的JDWP并不是基于JVM TI开发的
JVM TI支持的功能
线程相关事件->监控线程创建堆栈、锁信息ThreadStart:线程在执行方法前产生线程启动事件
ThreadEnd:线程结束事件
MonitorWait:wait方法调用后
MonitorWauted:wai方法完成等待
MonitorContendedEnter:当线程试图获取一个已经被其他线程持有的对象锁时
MonitorContendedEntered:当线程获取到对象锁继续执行时
类加载准备事件->监控类加载
ClassFileLoadHook:在类加载之前触发
ClassLoad:某个类首次被加载
ClassPrepare:某个类的准备阶段完成
异常事件->监控异常信息
Exception:有异常抛出的时候
ExceptionCatch:当捕获到一个异常的时候
调试相关
SingleStep:步进事件,可以实现相当细粒度的字节码执行顺序,这个功能可以探查多线程下的字节码执行序列
Breakpoint:当线程执行到一个带断点的位置,断点可以通过JVMTI setBreakpoint的方法来设置
方法执行
FramePop:当方法执行到return指令或者出现异常时候产生,手动调用NofityFramePop JVM TI函数也可产生该事件
MethodEntry:当开始执行一个java方法的时候
MethodExit:当方法执行完成后,产生异常退出时
FieldAccess:当访问了设置了观察点的属性时产生事件,观察点使用SetFieldAccessWatch函数设置
FieldModification:当设置了观察点的属性值被修改后,观察点使用SetDieldModificationWatch设置
GC->GC事件与时间
GarbageCollectionStart:GC启动时
GarbageCollectionFinish:GC结束后
对象事件->监控内存分配
ObjectFree:GC释放一个对象时
VMObjectAlloc:虚拟机分配一个对象的时候
其他
NativeMethodBind:在首次调用本地方法时或者调用JNI RegisterNatives的时候产生该事件,通过该回调可以将一个JNI调用切换到指定的方法上
JVM TI实现原理
JVM TI Agent的启动需要虚拟机的支持,我们的Agent和虚拟机运行在同一个进程中,虚拟机通过dlopen打开我们的Agent动态链接库,然后通过Agent_OnAttach方法来调用我们定义的初始化逻辑
JVM TI的原理其实很简单,以VmObjectAlloc事件为例,当我们通过SetEventNotificationMode函数设置JVMTI_EVENT_VM_OBJECT_ALLOC回调的时候,最终会调用到art:Runtime:Current()->GetHeap()->SetAllocationListener(listener)
在这个方法中,listener是JVM TI实现的一个虚拟机提供的art::gc::AllocationListener回调,当虚拟机分配对象内存的时候会调用该回调,同时在该回调函数里也会调用我们之前设置的callback方法,这样事件和相关的数据就会透传到我们的Agent里,来实现完成事件的监听
类似atrace和StrictMode,JVM TI的每个事件都需要在源码中埋点支持