1 JVMTI
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;
1.1 jvmtiEventVMInit的回调函数
虚拟机在创建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 eventsJvmtiEventController::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的回调函数
1.2 jvmtiEventClassFileLoadHook回调函数
钩子方法是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