heaptracker.c

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

C
1,014
字号
            /* Create single array of pointers to TraceInfo's, sort, and             *   print top gdata->maxDump top space users.             */            list = (TraceInfo**)calloc(gdata->traceInfoCount,                                               sizeof(TraceInfo*));            if ( list == NULL ) {                fatal_error("ERROR: Ran out of malloc() space\n");            }            count = 0;            for ( i = 0 ; i < HASH_BUCKET_COUNT ; i++ ) {                TraceInfo *tinfo;                tinfo = gdata->hashBuckets[i];                while ( tinfo != NULL ) {                    if ( count < gdata->traceInfoCount ) {                        list[count++] = tinfo;                    }                    tinfo = tinfo->next;                }            }            if ( count != gdata->traceInfoCount ) {                fatal_error("ERROR: Count found by iterate doesn't match ours:"                        " count=%d != traceInfoCount==%d\n",                        count, gdata->traceInfoCount);            }            qsort(list, count, sizeof(TraceInfo*), &compareInfo);            for ( i = 0 ; i < count ; i++ ) {                if ( i >= gdata->maxDump ) {                    break;                }                printTraceInfo(jvmti, i+1, list[i]);            }            (void)free(list);        }    } exitCriticalSection(jvmti);        }  /* Callback for JVMTI_EVENT_VM_OBJECT_ALLOC */static void JNICALLcbVMObjectAlloc(jvmtiEnv *jvmti, JNIEnv *env, jthread thread,                 jobject object, jclass object_klass, jlong size){    TraceInfo *tinfo;        if ( gdata->vmDead ) {        return;    }    tinfo = findTraceInfo(jvmti, thread, TRACE_VM_OBJECT);    tagObjectWithTraceInfo(jvmti, object, tinfo);}/* Callback for JVMTI_EVENT_OBJECT_FREE */static void JNICALLcbObjectFree(jvmtiEnv *jvmti, jlong tag){    TraceInfo *tinfo;      if ( gdata->vmDead ) {        return;    }        /* The object tag is actually a pointer to a TraceInfo structure */    tinfo = (TraceInfo*)(void*)(ptrdiff_t)tag;        /* Decrement the use count */    tinfo->useCount--;}/* Callback for JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */static void JNICALLcbClassFileLoadHook(jvmtiEnv *jvmti, 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){    enterCriticalSection(jvmti); {        /* It's possible we get here right after VmDeath event, be careful */        if ( !gdata->vmDead ) {            const char * classname;            /* Name can be NULL, make sure we avoid SEGV's */            if ( name == NULL ) {                classname = java_crw_demo_classname(class_data, class_data_len,                                NULL);                if ( classname == NULL ) {                    fatal_error("ERROR: No classname in classfile\n");                }            } else {                classname = strdup(name);                if ( classname == NULL ) {                    fatal_error("ERROR: Ran out of malloc() space\n");                }            }            *new_class_data_len = 0;            *new_class_data     = NULL;            /* The tracker class itself? */            if ( strcmp(classname, STRING(HEAP_TRACKER_class)) != 0 ) {                jint           cnum;                int            systemClass;                unsigned char *newImage;                long           newLength;                /* Get number for every class file image loaded */                cnum = gdata->ccount++;                /* Is it a system class? If the class load is before VmStart                 *   then we will consider it a system class that should                 *   be treated carefully. (See java_crw_demo)                 */                systemClass = 0;                if ( !gdata->vmStarted ) {                    systemClass = 1;                }                newImage = NULL;                newLength = 0;                /* Call the class file reader/write demo code */                java_crw_demo(cnum,                    classname,                    class_data,                    class_data_len,                    systemClass,                    STRING(HEAP_TRACKER_class),                    "L" STRING(HEAP_TRACKER_class) ";",                    NULL, NULL,                    NULL, NULL,                    STRING(HEAP_TRACKER_newobj), "(Ljava/lang/Object;)V",                    STRING(HEAP_TRACKER_newarr), "(Ljava/lang/Object;)V",                    &newImage,                    &newLength,                    NULL,                    NULL);                /* If we got back a new class image, return it back as "the"                 *   new class image. This must be JVMTI Allocate space.                 */                if ( newLength > 0 ) {                    unsigned char *jvmti_space;                    jvmti_space = (unsigned char *)allocate(jvmti, (jint)newLength);                    (void)memcpy((void*)jvmti_space, (void*)newImage, (int)newLength);                    *new_class_data_len = (jint)newLength;                    *new_class_data     = jvmti_space; /* VM will deallocate */                }                /* Always free up the space we get from java_crw_demo() */                if ( newImage != NULL ) {                    (void)free((void*)newImage); /* Free malloc() space with free() */                }            }                    (void)free((void*)classname);        }    } exitCriticalSection(jvmti);}/* Parse the options for this heapTracker agent */static voidparse_agent_options(char *options){    #define MAX_TOKEN_LENGTH        16    char  token[MAX_TOKEN_LENGTH];    char *next;    /* Defaults */    gdata->maxDump = 20;    /* Parse options and set flags in gdata */    if ( options==NULL ) {        return;    }       /* Get the first token from the options string. */    next = get_token(options, ",=", token, (int)sizeof(token));    /* While not at the end of the options string, process this option. */    while ( next != NULL ) {        if ( strcmp(token,"help")==0 ) {            stdout_message("The heapTracker JVMTI demo agent\n");            stdout_message("\n");            stdout_message(" java -agent:heapTracker[=options] ...\n");            stdout_message("\n");            stdout_message("The options are comma separated:\n");            stdout_message("\t help\t\t\t Print help information\n");            stdout_message("\t maxDump=n\t\t\t How many TraceInfo's to dump\n");            stdout_message("\n");            exit(0);        } else if ( strcmp(token,"maxDump")==0 ) {            char  number[MAX_TOKEN_LENGTH];                        next = get_token(next, ",=", number, (int)sizeof(number));            if ( next == NULL ) {                fatal_error("ERROR: Cannot parse maxDump=number: %s\n", options);            }            gdata->maxDump = atoi(number);        } else if ( token[0]!=0 ) {            /* We got a non-empty token and we don't know what it is. */            fatal_error("ERROR: Unknown option: %s\n", token);        }        /* Get the next token (returns NULL if there are no more) */        next = get_token(next, ",=", token, (int)sizeof(token));    }}/* Agent_OnLoad: This is called immediately after the shared library is  *   loaded. This is the first code executed. */JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved){    static GlobalAgentData data;    jvmtiEnv              *jvmti;    jvmtiError             error;    jint                   res;    TraceFlavor            flavor;    jvmtiCapabilities      capabilities;    jvmtiEventCallbacks    callbacks;    static Trace           empty;        /* Setup initial global agent data area      *   Use of static/extern data should be handled carefully here.     *   We need to make sure that we are able to cleanup after ourselves     *     so anything allocated in this library needs to be freed in     *     the Agent_OnUnload() function.     */    (void)memset((void*)&data, 0, sizeof(data));    gdata = &data;       /* First thing we need to do is get the jvmtiEnv* or JVMTI environment */    res = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_1);    if (res != JNI_OK) {        /* This means that the VM was unable to obtain this version of the         *   JVMTI interface, this is a fatal error.         */        fatal_error("ERROR: Unable to access JVMTI Version 1 (0x%x),"                " is your JDK a 5.0 or newer version?"                " JNIEnv's GetEnv() returned %d\n",               JVMTI_VERSION_1, res);    }    /* Here we save the jvmtiEnv* for Agent_OnUnload(). */    gdata->jvmti = jvmti;       /* Parse any options supplied on java command line */    parse_agent_options(options);       /* Immediately after getting the jvmtiEnv* we need to ask for the     *   capabilities this agent will need.      */    (void)memset(&capabilities,0, sizeof(capabilities));    capabilities.can_generate_all_class_hook_events = 1;    capabilities.can_tag_objects  = 1;    capabilities.can_generate_object_free_events  = 1;    capabilities.can_get_source_file_name  = 1;    capabilities.can_get_line_numbers  = 1;    capabilities.can_generate_vm_object_alloc_events  = 1;    error = (*jvmti)->AddCapabilities(jvmti, &capabilities);    check_jvmti_error(jvmti, error, "Unable to get necessary JVMTI capabilities.");        /* Next we need to provide the pointers to the callback functions to     *   to this jvmtiEnv*     */    (void)memset(&callbacks,0, sizeof(callbacks));    /* JVMTI_EVENT_VM_START */    callbacks.VMStart           = &cbVMStart;          /* JVMTI_EVENT_VM_INIT */    callbacks.VMInit            = &cbVMInit;          /* JVMTI_EVENT_VM_DEATH */    callbacks.VMDeath           = &cbVMDeath;         /* JVMTI_EVENT_OBJECT_FREE */    callbacks.ObjectFree        = &cbObjectFree;         /* JVMTI_EVENT_VM_OBJECT_ALLOC */    callbacks.VMObjectAlloc     = &cbVMObjectAlloc;         /* JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */    callbacks.ClassFileLoadHook = &cbClassFileLoadHook;     error = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, (jint)sizeof(callbacks));    check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks");       /* At first the only initial events we are interested in are VM     *   initialization, VM death, and Class File Loads.      *   Once the VM is initialized we will request more events.     */    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,                           JVMTI_EVENT_VM_START, (jthread)NULL);    check_jvmti_error(jvmti, error, "Cannot set event notification");    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,                           JVMTI_EVENT_VM_INIT, (jthread)NULL);    check_jvmti_error(jvmti, error, "Cannot set event notification");    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,                           JVMTI_EVENT_VM_DEATH, (jthread)NULL);    check_jvmti_error(jvmti, error, "Cannot set event notification");    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,                           JVMTI_EVENT_OBJECT_FREE, (jthread)NULL);    check_jvmti_error(jvmti, error, "Cannot set event notification");    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,                           JVMTI_EVENT_VM_OBJECT_ALLOC, (jthread)NULL);    check_jvmti_error(jvmti, error, "Cannot set event notification");    error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,                           JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, (jthread)NULL);    check_jvmti_error(jvmti, error, "Cannot set event notification");       /* Here we create a raw monitor for our use in this agent to     *   protect critical sections of code.     */    error = (*jvmti)->CreateRawMonitor(jvmti, "agent data", &(gdata->lock));    check_jvmti_error(jvmti, error, "Cannot create raw monitor");    /* Create the TraceInfo for various flavors of empty traces */    for ( flavor = TRACE_FIRST ; flavor <= TRACE_LAST ; flavor++ ) {        gdata->emptyTrace[flavor] =                newTraceInfo(&empty, hashTrace(&empty), flavor);    }    /* Add jar file to boot classpath */    add_demo_jar_to_bootclasspath(jvmti, "heapTracker");    /* We return JNI_OK to signify success */    return JNI_OK;}/* Agent_OnUnload: This is called immediately before the shared library is  *   unloaded. This is the last code executed. */JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm){    /* Skip any cleanup, VM is about to die anyway */}

⌨️ 快捷键说明

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