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 + -
显示快捷键?