JVMTI 全名JVM Tool Interface,是JVM暴露出来的一些供用户扩展的接口集合。JVMTI是基于事件驱动的,JVM每执行到一定的逻辑就会主动调用一些事件的回调接口,这些接口可以供开发者扩展自己的逻辑。
下面是JVMTI的一些回调接口
typedef struct {/* 50 : VM Initialization Event */ jvmtiEventVMInit VMInit; /* 51 : VM Death Event */ jvmtiEventVMDeath VMDeath; /* 52 : Thread Start */ jvmtiEventThreadStart ThreadStart;/* 53 : Thread End */ jvmtiEventThreadEnd ThreadEnd; /* 54 : Class File Load Hook */ jvmtiEventClassFileLoadHook ClassFileLoadHook; /* 55 : Class Load */ jvmtiEventClassLoad ClassLoad; /* 56 : Class Prepare */ jvmtiEventClassPrepare ClassPrepare;/* 57 : VM Start Event */ jvmtiEventVMStart VMStart;/* 58 : Exception */ jvmtiEventException Exception;/* 59 : Exception Catch */ jvmtiEventExceptionCatch ExceptionCatch; /* 60 : Single Step */ jvmtiEventSingleStep SingleStep;/* 61 : Frame Pop */ jvmtiEventFramePop FramePop;/* 62 : Breakpoint */ jvmtiEventBreakpoint Breakpoint; /* 63 : Field Access */ jvmtiEventFieldAccess FieldAccess;/* 64 : Field Modification */ jvmtiEventFieldModification FieldModification; /* 65 : Method Entry */ jvmtiEventMethodEntry MethodEntry;/* 66 : Method Exit */ jvmtiEventMethodExit MethodExit;/* 67 : Native Method Bind */ jvmtiEventNativeMethodBind NativeMethodBind;/* 68 : Compiled Method Load */ jvmtiEventCompiledMethodLoad CompiledMethodLoad;/* 69 : Compiled Method Unload */ jvmtiEventCompiledMethodUnload CompiledMethodUnload; /* 70 : Dynamic Code Generated */ jvmtiEventDynamicCodeGenerated DynamicCodeGenerated; /* 71 : Data Dump Request */ jvmtiEventDataDumpRequest DataDumpRequest;/* 72 */ jvmtiEventReserved reserved72;/* 73 : Monitor Wait */ jvmtiEventMonitorWait MonitorWait;/* 74 : Monitor Waited */ jvmtiEventMonitorWaited MonitorWaited;/* 75 : Monitor Contended Enter */ jvmtiEventMonitorContendedEnter MonitorContendedEnter;/* 76 : Monitor Contended Entered */ jvmtiEventMonitorContendedEntered MonitorContendedEntered;/* 77 */ jvmtiEventReserved reserved77;/* 78 */ jvmtiEventReserved reserved78; /* 79 */ jvmtiEventReserved reserved79; /* 80 : Resource Exhausted */ jvmtiEventResourceExhausted ResourceExhausted;/* 81 : Garbage Collection Start */ jvmtiEventGarbageCollectionStart GarbageCollectionStart;/* 82 : Garbage Collection Finish */ jvmtiEventGarbageCollectionFinish GarbageCollectionFinish;/* 83 : Object Free */ jvmtiEventObjectFree ObjectFree;/* 84 : VM Object Allocation */ jvmtiEventVMObjectAlloc VMObjectAlloc; } jvmtiEventCallbacks;
虚拟机在创建create_vm的时候,初始化了JVMTI的环境, JvmtiExport::post_vm_initialized(); 的方法中
void JvmtiExport::post_vm_initialized() { EVT_TRIG_TRACE(JVMTI_EVENT_VM_INIT, ("JVMTI Trg VM init event triggered" )); // can now enable events JvmtiEventController::vm_init(); JvmtiEnvIterator it; for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { if (env->is_enabled(JVMTI_EVENT_VM_INIT)) { EVT_TRACE(JVMTI_EVENT_VM_INIT, ("JVMTI Evt VM init event sent" )); JavaThread *thread = JavaThread::current(); JvmtiThreadEventMark jem(thread); JvmtiJavaThreadEventTransition jet(thread); jvmtiEventVMInit callback = env->callbacks()->VMInit; if (callback != NULL) { (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread()); } } } }代码中调用了VMInit的回调函数
钩子方法是jvmtiEventClassFileLoadHook 的方法,我们可以看代码:在classFileParser的文件中
instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, Handle class_loader,Handle protection_domain, KlassHandle host_klass, GrowableArray<Handle>* cp_patches, symbolHandle& parsed_name,bool verify, TRAPS) { …… if (JvmtiExport::should_post_class_file_load_hook()) { unsigned char* ptr = cfs->buffer(); unsigned char* end_ptr = cfs->buffer() + cfs->length(); JvmtiExport::post_class_file_load_hook(name, class_loader, protection_domain, &ptr, &end_ptr, &cached_class_file_bytes, &cached_class_file_length); if (ptr != cfs->buffer()) { // JVMTI agent has modified class file data. // Set new class file stream using JVMTI agent modified // class file data. cfs = new ClassFileStream(ptr, end_ptr - ptr, cfs->source()); set_stream(cfs); } } … }
在jvmtiexport::post_class_file_load_hook函数最后调用了post_to_env()函数
void post_to_env(JvmtiEnv* env, bool caching_needed) { unsigned char *new_data = NULL; jint new_len = 0; JvmtiClassFileLoadEventMark jem(_thread, _h_name, _class_loader, _h_protection_domain, _h_class_being_redefined); JvmtiJavaThreadEventTransition jet(_thread); JNIEnv* jni_env = (JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL)? NULL : jem.jni_env(); jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook; if (callback != NULL) { (*callback)(env->jvmti_external(), jni_env, jem.class_being_redefined(), jem.jloader(), jem.class_name(), jem.protection_domain(), _curr_len, _curr_data, &new_len, &new_data); } ...... }
函数中调用了jvmtiEventClassFileLoadHook 的钩子回调函数,也就是刚才在结构体中定义的jvmtiEventCallbacks