hprof_init.c

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

C
1,986
字号
/* * @(#)hprof_init.c	1.92 05/12/06 *  * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: *  * -Redistribution of source code must retain the above copyright notice, this *  list of conditions and the following disclaimer. *  * -Redistribution in binary form must reproduce the above copyright notice,  *  this list of conditions and the following disclaimer in the documentation *  and/or other materials provided with the distribution. *  * Neither the name of Sun Microsystems, Inc. or the names of contributors may  * be used to endorse or promote products derived from this software without  * specific prior written permission. *  * This software is provided "AS IS," without a warranty of any kind. ALL  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. *  * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. *//* Main source file, the basic JVMTI connection/startup code. */#include "hprof.h"#include "java_crw_demo.h"/* * This file contains all the startup logic (Agent_Onload) and *   connection to the JVMTI interface. * All JVMTI Event callbacks are in this file. * All setting of global data (gdata) is done here. * Options are parsed here. * Option help messages are here. * Termination handled here (VM_DEATH) and shutdown (Agent_OnUnload). * Spawning of the cpu sample loop thread and listener thread is done here. * * Use of private 'static' data has been limited, most shared static data *    should be found in the GlobalData structure pointed to by gdata *    (see hprof.h). * *//* The default output filenames. */#define DEFAULT_TXT_SUFFIX	".txt"#define DEFAULT_OUTPUTFILE	"java.hprof"#define DEFAULT_OUTPUTTEMP	"java.hprof.temp"/* The only global variable, defined by this library */GlobalData *gdata;/* Experimental options */#define EXPERIMENT_NO_EARLY_HOOK 0x1/* Default trace depth */#define DEFAULT_TRACE_DEPTH 4/* Default sample interval */#define DEFAULT_SAMPLE_INTERVAL 10/* Default cutoff */#define DEFAULT_CUTOFF_POINT 0.0001/* Stringize macros for help. */#define _TO_STR(a) #a#define TO_STR(a) _TO_STR(a)/* Macros to surround callback code (non-VM_DEATH callbacks). *   Note that this just keeps a count of the non-VM_DEATH callbacks that *   are currently active, it does not prevent these callbacks from *   operating in parallel. It's the VM_DEATH callback that will wait *   for all these callbacks to either complete and block, or just block. *   We need to hold back these threads so they don't die during the final *   VM_DEATH processing. *   If the VM_DEATH callback is active in the beginning, then this callback *   just blocks to prevent further execution of the thread. *   If the VM_DEATH callback is active at the end, then this callback *   will notify the VM_DEATH callback if it's the last one. *   In all cases, the last thing they do is Enter/Exit the monitor *   gdata->callbackBlock, which will block this callback if VM_DEATH *   is running. * *   WARNING: No not 'return' or 'goto' out of the BEGIN_CALLBACK/END_CALLBACK *            block, this will mess up the count. */#define BEGIN_CALLBACK()                                            \{ /* BEGIN OF CALLBACK */                                           \    jboolean bypass;                                                \    rawMonitorEnter(gdata->callbackLock);                           \    if (gdata->vm_death_callback_active) {                          \	/* VM_DEATH is active, we will bypass the CALLBACK CODE */  \	bypass = JNI_TRUE;                                          \	rawMonitorExit(gdata->callbackLock);                        \	/* Bypassed CALLBACKS block here until VM_DEATH done */     \	rawMonitorEnter(gdata->callbackBlock);                      \	rawMonitorExit(gdata->callbackBlock);                       \    } else {                                                        \	/* We will be executing the CALLBACK CODE in this case */   \	gdata->active_callbacks++;                                  \	bypass = JNI_FALSE;                                         \	rawMonitorExit(gdata->callbackLock);                        \    }                                                               \    if ( !bypass ) {                                                \        /* BODY OF CALLBACK CODE (with no callback locks held) */#define END_CALLBACK() /* Part of bypass if body */                 \        rawMonitorEnter(gdata->callbackLock);                       \	gdata->active_callbacks--;                                  \	/* If VM_DEATH is active, and last one, send notify. */     \	if (gdata->vm_death_callback_active) {                      \	    if (gdata->active_callbacks == 0) {                     \		rawMonitorNotifyAll(gdata->callbackLock);           \	    }                                                       \	}                                                           \	rawMonitorExit(gdata->callbackLock);                        \	/* Non-Bypassed CALLBACKS block here until VM_DEATH done */ \	rawMonitorEnter(gdata->callbackBlock);                      \	rawMonitorExit(gdata->callbackBlock);                       \    }                                                               \} /* END OF CALLBACK *//* Forward declarations */static void set_callbacks(jboolean on);/* ------------------------------------------------------------------- *//* Global data initialization *//* Get initialized global data area */static GlobalData *get_gdata(void){    static GlobalData data;    /* Create initial default values */    (void)memset(&data, 0, sizeof(GlobalData));        data.fd                             = -1; /* Non-zero file or socket. */    data.heap_fd                        = -1; /* For heap=dump, see hprof_io */    data.check_fd                       = -1; /* For heap=dump, see hprof_io */    data.max_trace_depth                = DEFAULT_TRACE_DEPTH;    data.prof_trace_depth               = DEFAULT_TRACE_DEPTH;    data.sample_interval                = DEFAULT_SAMPLE_INTERVAL;    data.lineno_in_traces               = JNI_TRUE;    data.output_format                  = 'a';      /* 'b' for binary */    data.cutoff_point                   = DEFAULT_CUTOFF_POINT;    data.dump_on_exit                   = JNI_TRUE;    data.gc_start_time                  = -1L;#ifdef DEBUG    data.debug			        = JNI_TRUE;    data.coredump		        = JNI_TRUE;#endif    data.micro_state_accounting        	= JNI_FALSE;    data.force_output        	        = JNI_TRUE;    data.verbose		        = JNI_TRUE;    data.primfields		        = JNI_TRUE;    data.primarrays		        = JNI_TRUE;        data.table_serial_number_start    = 1;    data.class_serial_number_start    = 100000;    data.thread_serial_number_start   = 200000;    data.trace_serial_number_start    = 300000;    data.object_serial_number_start   = 400000;    data.frame_serial_number_start    = 500000;    data.gref_serial_number_start     = 1;        data.table_serial_number_counter  = data.table_serial_number_start;    data.class_serial_number_counter  = data.class_serial_number_start;    data.thread_serial_number_counter = data.thread_serial_number_start;    data.trace_serial_number_counter  = data.trace_serial_number_start;    data.object_serial_number_counter = data.object_serial_number_start;    data.frame_serial_number_counter  = data.frame_serial_number_start;    data.gref_serial_number_counter   = data.gref_serial_number_start;       data.unknown_thread_serial_num    = data.thread_serial_number_counter++;    return &data;}/* ------------------------------------------------------------------- *//* Error handler callback for the java_crw_demo (classfile read write) functions. */static voidmy_crw_fatal_error_handler(const char * msg, const char *file, int line){    char errmsg[256];        (void)md_snprintf(errmsg, sizeof(errmsg), 		"%s [%s:%d]", msg, file, line);    errmsg[sizeof(errmsg)-1] = 0;    HPROF_ERROR(JNI_TRUE, errmsg);}static voidlist_all_tables(void){    string_list();    class_list();    frame_list();    site_list();    object_list();    trace_list();    monitor_list();    tls_list();    loader_list();}/* ------------------------------------------------------------------- *//* Option Parsing support *//** * Socket connection *//* * Return a socket  connect()ed to a "hostname" that is * accept()ing heap profile data on "port." Return a value <= 0 if * such a connection can't be made. */static int connect_to_socket(char *hostname, unsigned short port){    int fd;        if (port == 0 || port > 65535) {        HPROF_ERROR(JNI_FALSE, "invalid port number");        return -1;    }    if (hostname == NULL) {        HPROF_ERROR(JNI_FALSE, "hostname is NULL");        return -1;    }    /* create a socket */    fd = md_connect(hostname, port);    return fd;}/* Accept a filename, and adjust the name so that it is unique for this PID */static voidmake_unique_filename(char **filename){    int fd;    /* Find a file that doesn't exist */    fd = md_open(*filename);    if ( fd >= 0 ) {	int   pid;	char *new_name;	char *old_name;	char *prefix;	char  suffix[5];	int   new_len;	/* Close the file. */	md_close(fd);		/* Make filename name.PID[.txt] */	pid = md_getpid();	old_name = *filename;	new_len = (int)strlen(old_name)+64;	new_name = HPROF_MALLOC(new_len);	prefix = old_name;	suffix[0] = 0;	/* Look for .txt suffix if not binary output */	if (gdata->output_format != 'b') {	    char *dot;	    char *format_suffix;	    format_suffix = DEFAULT_TXT_SUFFIX;	    	    (void)strcpy(suffix, format_suffix);	    	    dot = strrchr(old_name, '.');	    if ( dot != NULL ) {		int i;		int slen;		int match;		slen = (int)strlen(format_suffix);		match = 1;		for ( i = 0; i < slen; i++ ) {		    if ( dot[i]==0 ||			 tolower(format_suffix[i]) != tolower(dot[i]) ) {			match = 0;			break;		    }		}		if ( match ) {		    (void)strcpy(suffix, dot);		    *dot = 0; /* truncates prefix and old_name */	        }	    }	}	/* Construct the name */	(void)md_snprintf(new_name, new_len, 		   "%s.%d%s", prefix, pid, suffix); 	*filename = new_name;	HPROF_FREE(old_name);	/* Odds are with Windows, this file may not be so unique. */	(void)remove(gdata->output_filename);    }}static int get_tok(char **src, char *buf, int buflen, int sep){    int len;    char *p;        buf[0] = 0;    if ( **src == 0 ) {	return 0;    }    p = strchr(*src, sep);    if ( p==NULL ) {	len = (int)strlen(*src);	p = (*src) + len;    } else {	/*LINTED*/	len = (int)(p - (*src));    }    if ( (len+1) > buflen ) {	return 0;    }    (void)memcpy(buf, *src, len);    buf[len] = 0;    if ( *p != 0 && *p == sep ) {	(*src) = p+1;    } else {	(*src) = p;    }    return len;}static jbooleansetBinarySwitch(char **src, jboolean *ptr){    char buf[80];        if (!get_tok(src, buf, (int)sizeof(buf), ',')) {        return JNI_FALSE;    }    if (strcmp(buf, "y") == 0) {        *ptr = JNI_TRUE;    } else if (strcmp(buf, "n") == 0) {        *ptr = JNI_FALSE;    } else {        return JNI_FALSE;    }    return JNI_TRUE;}static void print_usage(void){        (void)fprintf(stdout,"\n""     HPROF: Heap and CPU Profiling Agent (JVMTI Demonstration Code)\n""\n"AGENTNAME " usage: java " AGENTLIB "=[help]|[<option>=<value>, ...]\n""\n""Option Name and Value  Description                    Default\n""---------------------  -----------                    -------\n""heap=dump|sites|all    heap profiling                 all\n""cpu=samples|times|old  CPU usage                      off\n""monitor=y|n            monitor contention             n\n""format=a|b             text(txt) or binary output     a\n""file=<file>            write data to file             " DEFAULT_OUTPUTFILE "[{" DEFAULT_TXT_SUFFIX "}]\n""net=<host>:<port>      send data over a socket        off\n""depth=<size>           stack trace depth              " TO_STR(DEFAULT_TRACE_DEPTH) "\n""interval=<ms>          sample interval in ms          " TO_STR(DEFAULT_SAMPLE_INTERVAL) "\n""cutoff=<value>         output cutoff point            " TO_STR(DEFAULT_CUTOFF_POINT) "\n""lineno=y|n             line number in traces?         y\n""thread=y|n             thread in traces?              n\n""doe=y|n                dump on exit?                  y\n""msa=y|n                Solaris micro state accounting n\n""force=y|n              force output to <file>         y\n""verbose=y|n            print messages about dumps     y\n"

⌨️ 快捷键说明

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