hprof_init.c
来自「一个小公司要求给写的很简单的任务管理系统。」· C语言 代码 · 共 1,986 行 · 第 1/5 页
C
1,986 行
/* Used to ID HPROF generated items */ gdata->hprof_trace_index = tls_get_trace(tls_index, env, gdata->max_trace_depth, JNI_FALSE); gdata->hprof_site_index = site_find_or_create( cnum, gdata->hprof_trace_index); if ( gdata->logflags & LOG_DUMP_LISTS ) { list_all_tables(); } /* Prime the class table */ reset_class_load_status(env, thread); /* Find the tracker jclass and jmethodID's (does JNI calls) */ if ( gdata->bci ) { tracker_setup_methods(env); } /* Start any agent threads (does JNI, JVMTI, and Java calls) */ /* Thread to watch for gc_finish events */ rawMonitorEnter(gdata->gc_finish_lock); { createAgentThread(env, "HPROF gc_finish watcher", &gc_finish_watcher); } rawMonitorExit(gdata->gc_finish_lock); /* Start up listener thread if we need it */ if ( gdata->socket ) { listener_init(env); } /* Start up cpu sampling thread if we need it */ if ( gdata->cpu_sampling ) { /* Note: this could also get started later (see cpu) */ cpu_sample_init(env); } /* Setup event modes */ setup_event_mode(JNI_FALSE, JVMTI_ENABLE); /* Engage tracking (sets Java Tracker field so injections call into * agent library). */ if ( gdata->bci ) { tracker_engage(env); } /* Indicate the VM is initialized now */ gdata->jvm_initialized = JNI_TRUE; gdata->jvm_initializing = JNI_FALSE; LOG("cbVMInit end"); } rawMonitorExit(gdata->data_access_lock);}/* JVMTI_EVENT_VM_DEATH */static void JNICALLcbVMDeath(jvmtiEnv *jvmti, JNIEnv *env){ /* * Use local flag to minimize gdata->dump_lock hold time. */ jboolean need_to_dump = JNI_FALSE; LOG("cbVMDeath"); /* Shutdown thread watching gc_finish, outside CALLBACK locks. * We need to make sure the watcher thread is done doing any cleanup * work before we continue here. */ rawMonitorEnter(gdata->gc_finish_lock); { /* Notify watcher thread to finish up, it will send * another notify when done. If the watcher thread is busy * cleaning up, it will detect gc_finish_stop_request when it's done. * Then it sets gc_finish_active to JNI_FALSE and will notify us. * If the watcher thread is waiting to be notified, then the * notification wakes it up. * We do not want to do the VM_DEATH while the gc_finish * watcher thread is in the middle of a cleanup. */ gdata->gc_finish_stop_request = JNI_TRUE; rawMonitorNotifyAll(gdata->gc_finish_lock); /* Wait for the gc_finish watcher thread to notify us it's done */ while ( gdata->gc_finish_active ) { rawMonitorWait(gdata->gc_finish_lock,0); } } rawMonitorExit(gdata->gc_finish_lock); /* The gc_finish watcher thread should be done now, or done shortly. */ /* BEGIN_CALLBACK/END_CALLBACK handling. */ /* The callbackBlock prevents any active callbacks from returning * back to the VM, and also blocks all new callbacks. * We want to prevent any threads from premature death, so * that we don't have worry about that during thread queries * in this final dump process. */ rawMonitorEnter(gdata->callbackBlock); { /* We need to wait for all callbacks actively executing to block * on exit, and new ones will block on entry. * The BEGIN_CALLBACK/END_CALLBACK macros keep track of callbacks * that are active. * Once the last active callback is done, it will notify this * thread and block. */ rawMonitorEnter(gdata->callbackLock); { /* Turn off native calls */ if ( gdata->bci ) { tracker_disengage(env); } gdata->vm_death_callback_active = JNI_TRUE; while (gdata->active_callbacks > 0) { rawMonitorWait(gdata->callbackLock, 0); } } rawMonitorExit(gdata->callbackLock); /* Now we know that no threads will die on us, being blocked * on some event callback, at a minimum ThreadEnd. */ /* Make some basic checks. */ rawMonitorEnter(gdata->data_access_lock); { if ( gdata->jvm_initializing ) { HPROF_ERROR(JNI_TRUE, "VM Death during VM Init"); return; } if ( !gdata->jvm_initialized ) { HPROF_ERROR(JNI_TRUE, "VM Death before VM Init"); return; } if (gdata->jvm_shut_down) { HPROF_ERROR(JNI_TRUE, "VM Death more than once?"); return; } } rawMonitorExit(gdata->data_access_lock); /* Shutdown the cpu loop thread */ if ( gdata->cpu_sampling ) { cpu_sample_term(env); } /* Time to dump the final data */ rawMonitorEnter(gdata->dump_lock); { gdata->jvm_shut_down = JNI_TRUE; if (!gdata->dump_in_process) { need_to_dump = JNI_TRUE; gdata->dump_in_process = JNI_TRUE; /* * Setting gdata->dump_in_process will cause cpu sampling to pause * (if we are sampling). We don't resume sampling after the * dump_all_data() call below because the VM is shutting * down. */ } } rawMonitorExit(gdata->dump_lock); /* Dump everything if we need to */ if (gdata->dump_on_exit && need_to_dump) { dump_all_data(env); } /* Disable all events and callbacks now, all of them. * NOTE: It's important that this be done after the dump * it prevents other threads from messing up the data * because they will block on ThreadStart and ThreadEnd * events due to the CALLBACK block. */ set_callbacks(JNI_FALSE); setup_event_mode(JNI_FALSE, JVMTI_DISABLE); setup_event_mode(JNI_TRUE, JVMTI_DISABLE); /* Write tail of file */ io_write_file_footer(); } rawMonitorExit(gdata->callbackBlock); /* Shutdown the listener thread and socket, or flush I/O buffers */ if (gdata->socket) { listener_term(env); } else { io_flush(); } /* Close the file descriptors down */ if ( gdata->fd >= 0 ) { (void)md_close(gdata->fd); gdata->fd = -1; if ( gdata->logflags & LOG_CHECK_BINARY ) { if (gdata->output_format == 'b' && gdata->output_filename != NULL) { check_binary_file(gdata->output_filename); } } } if ( gdata->heap_fd >= 0 ) { (void)md_close(gdata->heap_fd); gdata->heap_fd = -1; } if ( gdata->check_fd >= 0 ) { (void)md_close(gdata->check_fd); gdata->check_fd = -1; } /* Remove the temporary heap file */ if (gdata->heap_dump) { (void)remove(gdata->heapfilename); } /* If logging, dump the tables */ if ( gdata->logflags & LOG_DUMP_LISTS ) { list_all_tables(); } /* Make sure all global references are deleted */ class_delete_global_references(env); loader_delete_global_references(env); tls_delete_global_references(env); } /* JVMTI_EVENT_THREAD_START */static void JNICALLcbThreadStart(jvmtiEnv *jvmti, JNIEnv *env, jthread thread){ LOG3("cbThreadStart", "thread is", (int)(long)(ptrdiff_t)thread); BEGIN_CALLBACK() { event_thread_start(env, thread); } END_CALLBACK();}/* JVMTI_EVENT_THREAD_END */static void JNICALLcbThreadEnd(jvmtiEnv *jvmti, JNIEnv *env, jthread thread){ LOG3("cbThreadEnd", "thread is", (int)(long)(ptrdiff_t)thread); BEGIN_CALLBACK() { event_thread_end(env, thread); } END_CALLBACK();}/* JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */static void JNICALLcbClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv* env, jclass class_being_redefined, jobject loader, const char* name, jobject protection_domain, jint class_data_len, const unsigned char* class_data, jint* new_class_data_len, unsigned char** new_class_data){ /* WARNING: This will be called before VM_INIT. */ LOG2("cbClassFileLoadHook:",(name==NULL?"Unknown":name)); if (!gdata->bci) { return; } BEGIN_CALLBACK() { rawMonitorEnter(gdata->data_access_lock); { const char *classname; if ( gdata->bci_counter == 0 ) { /* Prime the system classes */ class_prime_system_classes(); } gdata->bci_counter++; *new_class_data_len = 0; *new_class_data = NULL; /* Name could be NULL */ if ( name == NULL ) { classname = ((JavaCrwDemoClassname) (gdata->java_crw_demo_classname_function)) (class_data, class_data_len, &my_crw_fatal_error_handler); if ( classname == NULL ) { HPROF_ERROR(JNI_TRUE, "No classname in classfile"); } } else { classname = strdup(name); if ( classname == NULL ) { HPROF_ERROR(JNI_TRUE, "Ran out of malloc() space"); } } /* The tracker class itself? */ if ( strcmp(classname, TRACKER_CLASS_NAME) != 0 ) { ClassIndex cnum; int system_class; unsigned char * new_image; long new_length; int len; char *signature; LoaderIndex loader_index; LOG2("cbClassFileLoadHook injecting class" , classname); /* Define a unique class number for this class */ len = (int)strlen(classname); signature = HPROF_MALLOC(len+3); signature[0] = JVM_SIGNATURE_CLASS; (void)memcpy(signature+1, classname, len); signature[len+1] = JVM_SIGNATURE_ENDCLASS; signature[len+2] = 0; loader_index = loader_find_or_create(env,loader); if ( class_being_redefined != NULL ) { cnum = class_find_or_create(signature, loader_index); } else { cnum = class_create(signature, loader_index); } HPROF_FREE(signature); signature = NULL; /* Make sure class doesn't get unloaded by accident */ class_add_status(cnum, CLASS_IN_LOAD_LIST); /* Is it a system class? */ system_class = 0; if ( (!gdata->jvm_initialized) && (!gdata->jvm_initializing) && ( ( class_get_status(cnum) & CLASS_SYSTEM) != 0 || gdata->bci_counter < 8 ) ) { system_class = 1; LOG2(classname, " is a system class"); } new_image = NULL; new_length = 0; /* Call the class file reader/write demo code */ ((JavaCrwDemo)(gdata->java_crw_demo_function))( cnum, classname, class_data, class_data_len, system_class, TRACKER_CLASS_NAME, TRACKER_CLASS_SIG, (gdata->cpu_timing)?TRACKER_CALL_NAME:NULL, (gdata->cpu_timing)?TRACKER_CALL_SIG:NULL, (gdata->cpu_timing)?TRACKER_RETURN_NAME:NULL, (gdata->cpu_timing)?TRACKER_RETURN_SIG:NULL, (gdata->obj_watch)?TRACKER_OBJECT_INIT_NAME:NULL, (gdata->obj_watch)?TRACKER_OBJECT_INIT_SIG:NULL, (gdata->obj_watch)?TRACKER_NEWARRAY_NAME:NULL, (gdata->obj_watch)?TRACKER_NEWARRAY_SIG:NULL, &new_image, &new_length, &my_crw_fatal_error_handler, &class_set_methods); if ( new_length > 0 ) { unsigned char *jvmti_space; LOG2("cbClassFileLoadHook DID inject this class", classname); jvmti_space = (unsigned char *)jvmtiAllocate((jint)new_length); (void)memcpy((void*)jvmti_space, (void*)new_image, (int)new_length); *new_class_data_len = (jint)new_length; *new_class_data = jvmti_space; /* VM will deallocate */ } else { LOG2("cbClassFileLoadHook DID NOT inject this class", classname); *new_class_data_len = 0; *new_class_data = NULL; } if ( new_image != NULL ) { (void)free((void*)new_image); /* Free malloc() space with free() */ } } (void)free((void*)classname); } rawMonitorExit(gdata->data_access_lock); } END_CALLBACK();}/* JVMTI_EVENT_CLASS_LOAD */static void JNICALLcbClassLoad(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass){ /* WARNING: This MAY be called before VM_INIT. */ LOG("cbClassLoad"); BEGIN_CALLBACK() { rawMonitorEnter(gdata->data_access_lock); { WITH_LOCAL_REFS(env, 1) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?