Esempio n. 1
0
/* Lookup or create a new TraceInfo */
static TraceInfo *
lookupOrEnter(jvmtiEnv *jvmti, Trace *trace, TraceFlavor flavor)
{
    TraceInfo *tinfo;
    jlong      hashCode;

    /* Calculate hash code (outside critical section to lessen contention) */
    hashCode = hashTrace(trace);

    /* Do a lookup in the hash table */
    enterCriticalSection(jvmti);
    {
        TraceInfo *prev;
        int        hashIndex;

        /* Start with first item in hash buck chain */
        prev = NULL;
        hashIndex = (int)(hashCode & HASH_INDEX_MASK);
        tinfo = gdata->hashBuckets[hashIndex];
        while ( tinfo != NULL ) {
            if ( tinfo->hashCode == hashCode &&
                    memcmp(trace, &(tinfo->trace), sizeof(Trace))==0 ) {
                /* We found one that matches, move to head of bucket chain */
                if ( prev != NULL ) {
                    /* Remove from list and add to head of list */
                    prev->next = tinfo->next;
                    tinfo->next = gdata->hashBuckets[hashIndex];
                    gdata->hashBuckets[hashIndex] = tinfo;
                }
                /* Break out */
                break;
            }
            prev = tinfo;
            tinfo = tinfo->next;
        }

        /* If we didn't find anything we need to enter a new entry */
        if ( tinfo == NULL ) {
            /* Create new hash table element */
            tinfo = newTraceInfo(trace, hashCode, flavor);
        }

        /* Update stats */
        (void)updateStats(tinfo);

    }
    exitCriticalSection(jvmti);

    return tinfo;
}
/* 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;
}