Java Instrument (二) JVMTI

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 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的回调函数

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

你可能感兴趣的:(java,jvmti,instrument)