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