hprof_init.c

来自「一个小公司要求给写的很简单的任务管理系统。」· C语言 代码 · 共 1,986 行 · 第 1/5 页

C
1,986
字号
	    if ( gdata->debug ) {	        gdata->logflags |= LOG_CHECK_BINARY;	    }	    gdata->heap_fd = md_creat_binary(gdata->heapfilename);	} else {	    gdata->heap_fd = md_creat(gdata->heapfilename);	}	if ( gdata->heap_fd < 0 ) {	    char errmsg[FILENAME_MAX+80];            (void)md_snprintf(errmsg, sizeof(errmsg),                     "can't create temp heap file: %s", gdata->heapfilename);                    errmsg[sizeof(errmsg)-1] = 0;            HPROF_ERROR(JNI_TRUE, errmsg);	}    }        if ( gdata->net_port > 0 ) {        LOG2("Agent_OnLoad", "Connecting to socket");        gdata->fd = connect_to_socket(gdata->net_hostname, (unsigned short)gdata->net_port);        if (gdata->fd <= 0) {	    char errmsg[120];                (void)md_snprintf(errmsg, sizeof(errmsg),                "can't connect to %s:%u", gdata->net_hostname, gdata->net_port);            errmsg[sizeof(errmsg)-1] = 0;            HPROF_ERROR(JNI_FALSE, errmsg);            error_exit_process(1);        }        gdata->socket = JNI_TRUE;    } else {	/* If going out to a file, obey the force=y|n option */	if ( !gdata->force_output ) {            make_unique_filename(&(gdata->output_filename));	}	/* Make doubly sure this file does NOT exist */	(void)remove(gdata->output_filename);	/* Create the file */	if (gdata->output_format == 'b') {            gdata->fd = md_creat_binary(gdata->output_filename);        } else {            gdata->fd = md_creat(gdata->output_filename);        }        if (gdata->fd < 0) {	    char errmsg[FILENAME_MAX+80];                (void)md_snprintf(errmsg, sizeof(errmsg), 		"can't create profile file: %s", gdata->output_filename);            errmsg[sizeof(errmsg)-1] = 0;	    HPROF_ERROR(JNI_FALSE, errmsg);	    error_exit_process(1);        }    }}/* ------------------------------------------------------------------- *//* Data reset and dump functions */static void reset_all_data(void){    if (gdata->cpu_sampling || gdata->cpu_timing || gdata->monitor_tracing) {        rawMonitorEnter(gdata->data_access_lock);    }    if (gdata->cpu_sampling || gdata->cpu_timing) {        trace_clear_cost();    }    if (gdata->monitor_tracing) {        monitor_clear();    }    if (gdata->cpu_sampling || gdata->cpu_timing || gdata->monitor_tracing) {        rawMonitorExit(gdata->data_access_lock);    }}static void reset_class_load_status(JNIEnv *env, jthread thread);static void dump_all_data(JNIEnv *env){    verbose_message("Dumping");    if (gdata->monitor_tracing) {        verbose_message(" contended monitor usage ...");        tls_dump_monitor_state(env);        monitor_write_contended_time(env, gdata->cutoff_point);    }    if (gdata->heap_dump) {        verbose_message(" Java heap ...");	/* Update the class table */	reset_class_load_status(env, NULL);        site_heapdump(env);     }    if (gdata->alloc_sites) {        verbose_message(" allocation sites ...");        site_write(env, 0, gdata->cutoff_point);    }    if (gdata->cpu_sampling) {        verbose_message(" CPU usage by sampling running threads ...");        trace_output_cost(env, gdata->cutoff_point);    }    if (gdata->cpu_timing) {        if (!gdata->old_timing_format) {            verbose_message(" CPU usage by timing methods ...");            trace_output_cost(env, gdata->cutoff_point);        } else {            verbose_message(" CPU usage in old prof format ...");            trace_output_cost_in_prof_format(env);        }    }    reset_all_data();    io_flush();    verbose_message(" done.\n");}/* ------------------------------------------------------------------- *//* Dealing with class load and unload status */static voidreset_class_load_status(JNIEnv *env, jthread thread){        WITH_LOCAL_REFS(env, 1) {	jint    class_count;	jclass *classes;	jint    i;	/* Get all classes from JVMTI, make sure they are in the class table. */	getLoadedClasses(&classes, &class_count);	/* We don't know if the class list has changed really, so we	 *    guess by the class count changing. Don't want to do	 *    a bunch of work on classes when it's unnecessary.	 *    I assume that even though we have global references on the	 *    jclass object that the class is still considered unloaded.	 *    (e.g. GC of jclass isn't required for it to be included	 *    in the unloaded list, or not in the load list)	 *    [Note: Use of Weak references was a performance problem.]	 */	if ( class_count != gdata->class_count ) {            rawMonitorEnter(gdata->data_access_lock); {				/* Unmark the classes in the load list */		class_all_status_remove(CLASS_IN_LOAD_LIST);				/* Pretend like it was a class load event */		for ( i = 0 ; i < class_count ; i++ ) {		    jobject loader;		    		    loader = getClassLoader(classes[i]);		    event_class_load(env, thread, classes[i], loader);		}		/* Process the classes that have been unloaded */		class_do_unloads(env);            	    } rawMonitorExit(gdata->data_access_lock);		}	/* Free the space and save the count. */	jvmtiDeallocate(classes);	gdata->class_count = class_count;        } END_WITH_LOCAL_REFS;}/* A GC or Death event has happened, so do some cleanup */static voidobject_free_cleanup(JNIEnv *env, jboolean force_class_table_reset){    Stack *stack;        /* Then we process the ObjectFreeStack */    rawMonitorEnter(gdata->object_free_lock); {	stack = gdata->object_free_stack;	gdata->object_free_stack = NULL; /* Will trigger new stack */    } rawMonitorExit(gdata->object_free_lock);    /* Notice we just grabbed the stack of freed objects so     *    any object free events will create a new stack.     */    if ( stack != NULL ) {	int count;	int i;		count = stack_depth(stack);	/* If we saw something freed in this GC */	if ( count > 0 ) {		    for ( i = 0 ; i < count ; i++ ) {		ObjectIndex object_index;		jlong tag;				tag = *(jlong*)stack_element(stack,i);		    object_index = tag_extract(tag);		(void)object_free(object_index);	    }	    	    /* We reset the class load status (only do this once) */	    reset_class_load_status(env, NULL);	    force_class_table_reset = JNI_FALSE;		}		/* Just terminate this stack object */	stack_term(stack);    }        /* We reset the class load status if we haven't and need to */    if ( force_class_table_reset ) {	reset_class_load_status(env, NULL);    }    }/* Main function for thread that watches for GC finish events */static void JNICALLgc_finish_watcher(jvmtiEnv *jvmti, JNIEnv *env, void *p){    jboolean active;    active = JNI_TRUE;       /* Indicate the watcher thread is active */    rawMonitorEnter(gdata->gc_finish_lock); {        gdata->gc_finish_active = JNI_TRUE;    } rawMonitorExit(gdata->gc_finish_lock);       /* Loop while active */    while ( active ) {        jboolean do_cleanup;		do_cleanup = JNI_FALSE;	rawMonitorEnter(gdata->gc_finish_lock); {	    /* Don't wait if VM_DEATH wants us to quit */	    if ( gdata->gc_finish_stop_request ) {		/* Time to terminate */		active = JNI_FALSE;	    } else {		/* Wait for notification to do cleanup, or terminate */		rawMonitorWait(gdata->gc_finish_lock, 0);		/* After wait, check to see if VM_DEATH wants us to quit */	        if ( gdata->gc_finish_stop_request ) {		    /* Time to terminate */		    active = JNI_FALSE;		}	    }	    if ( active && gdata->gc_finish > 0 ) {		/* Time to cleanup, reset count and prepare for cleanup */	        gdata->gc_finish = 0;		do_cleanup = JNI_TRUE;	    }	} rawMonitorExit(gdata->gc_finish_lock);	/* Do the cleanup if requested outside gc_finish_lock */	if ( do_cleanup ) {	    /* Free up all freed objects, don't force class table reset 	     *   We cannot let the VM_DEATH complete while we are doing	     *   this cleanup. So if during this, VM_DEATH happens, 	     *   the VM_DEATH callback should block waiting for this	     *   loop to terminate, and send a notification to the	     *   VM_DEATH thread.	     */	    object_free_cleanup(env, JNI_FALSE);	    /* Cleanup the tls table where the Thread objects were GC'd */	    tls_garbage_collect(env);	}    }       /* Falling out means VM_DEATH is happening, we need to notify VM_DEATH     *    that we are done doing the cleanup. VM_DEATH is waiting on this     *    notify.     */    rawMonitorEnter(gdata->gc_finish_lock); {        gdata->gc_finish_active = JNI_FALSE;        rawMonitorNotifyAll(gdata->gc_finish_lock);    } rawMonitorExit(gdata->gc_finish_lock);}/* ------------------------------------------------------------------- *//* JVMTI Event callback functions */static voidsetup_event_mode(jboolean onload_set_only, jvmtiEventMode state){    if ( onload_set_only ) {	setEventNotificationMode(state, 			JVMTI_EVENT_VM_INIT,                   NULL);	setEventNotificationMode(state, 			JVMTI_EVENT_VM_DEATH,                  NULL);	if (gdata->bci) {	    setEventNotificationMode(state, 			JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,      NULL);	}    } else {         /* Enable all other JVMTI events of interest now. */	setEventNotificationMode(state, 			JVMTI_EVENT_THREAD_START,              NULL);	setEventNotificationMode(state, 			JVMTI_EVENT_THREAD_END,                NULL);	setEventNotificationMode(state, 		        JVMTI_EVENT_CLASS_LOAD,                NULL);	setEventNotificationMode(state, 		        JVMTI_EVENT_CLASS_PREPARE,             NULL);	setEventNotificationMode(state, 			JVMTI_EVENT_DATA_DUMP_REQUEST,         NULL);	if (gdata->cpu_timing) {	    setEventNotificationMode(state, 			JVMTI_EVENT_EXCEPTION_CATCH,           NULL);	}	if (gdata->monitor_tracing) {	    setEventNotificationMode(state, 			JVMTI_EVENT_MONITOR_WAIT,              NULL);	    setEventNotificationMode(state, 			JVMTI_EVENT_MONITOR_WAITED,            NULL);	    setEventNotificationMode(state, 			JVMTI_EVENT_MONITOR_CONTENDED_ENTER,   NULL);	    setEventNotificationMode(state, 			JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL);	}	if (gdata->obj_watch) {	    setEventNotificationMode(state, 			JVMTI_EVENT_OBJECT_FREE,               NULL);	}	setEventNotificationMode(state, 			JVMTI_EVENT_GARBAGE_COLLECTION_START,  NULL);	setEventNotificationMode(state, 			JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL);    }       }    /* JVMTI_EVENT_VM_INIT */static void JNICALLcbVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread){    rawMonitorEnter(gdata->data_access_lock); {	LoaderIndex loader_index;	ClassIndex  cnum;	TlsIndex    tls_index;        gdata->jvm_initializing = JNI_TRUE;    	/* Header to use in heap dumps */	gdata->header    = "JAVA PROFILE 1.0.1";	gdata->segmented = JNI_FALSE;	if (gdata->output_format == 'b') {	    /* We need JNI here to call in and get the current maximum memory */	    gdata->maxMemory      = getMaxMemory(env);	    gdata->maxHeapSegment = (jlong)2000000000;	    /* More than 2Gig triggers segments and 1.0.2 */ 	    if ( gdata->maxMemory >= gdata->maxHeapSegment ) {	        gdata->header    = "JAVA PROFILE 1.0.2";	        gdata->segmented = JNI_TRUE; /* 1.0.2 */	    }	}	/* We write the initial header after the VM initializes now	 *    because we needed to use JNI to get maxMemory and determine if	 *    a 1.0.1 or a 1.0.2 header will be used.	 *    This used to be done in Agent_OnLoad.	 */	io_write_file_header();		LOG("cbVMInit begin");     	/* Create a system loader entry first */	loader_index 	        = loader_find_or_create(NULL,NULL);        /* Find the thread jclass (does JNI calls) */        gdata->thread_cnum = class_find_or_create("Ljava/lang/Thread;", 			loader_index);	class_add_status(gdata->thread_cnum, CLASS_SYSTEM);        	/* Issue fake system thread start */	tls_index = tls_find_or_create(env, thread);		/* Setup the Tracker class (should be first class in table) */	tracker_setup_class();		/* Find selected system classes to keep track of */	gdata->system_class_size = 0;	cnum = class_find_or_create("Ljava/lang/Object;", loader_index);	gdata->system_trace_index = tls_get_trace(tls_index, env,				gdata->max_trace_depth, JNI_FALSE);	gdata->system_object_site_index = site_find_or_create(		    cnum, gdata->system_trace_index);	

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?