Example #1
0
/* Worker thread that waits for garbage collections */
static void JNICALL
worker(jvmtiEnv* jvmti, JNIEnv* jni, void *p)
{
    jvmtiError err;

    stdout_message("GC worker started...\n");

    for (;;) {
        err = (*jvmti)->RawMonitorEnter(jvmti, lock);
        check_jvmti_error(jvmti, err, "raw monitor enter");
        while (gc_count == 0) {
            err = (*jvmti)->RawMonitorWait(jvmti, lock, 0);
            if (err != JVMTI_ERROR_NONE) {
                err = (*jvmti)->RawMonitorExit(jvmti, lock);
                check_jvmti_error(jvmti, err, "raw monitor wait");
                return;
            }
        }
        gc_count = 0;

        err = (*jvmti)->RawMonitorExit(jvmti, lock);
        check_jvmti_error(jvmti, err, "raw monitor exit");

        /* Perform arbitrary JVMTI/JNI work here to do post-GC cleanup */
        stdout_message("post-GarbageCollectionFinish actions...\n");
    }
}
Example #2
0
/* VM initialization and VM death calls to Agent */
Agent::Agent(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
    stdout_message("Agent created..\n");
    stdout_message("VMInit...\n");
    /* Start monitor list */
    monitor_count = 0;
    monitor_list_size = initial_monitor_list_size;
    monitor_list = (Monitor**)
        malloc(monitor_list_size*(int)sizeof(Monitor*));
}
Example #3
0
/* VM initialization and VM death calls to Agent */
Agent::Agent(jvmtiEnv *jvmti, JNIEnv *env, jthread thread) 
{
    jvmtiError err;
    
    stdout_message("Agent created..\n");
    stdout_message("VMInit...\n");
    /* Create a Monitor lock to use */
    err = jvmti->CreateRawMonitor("waiters Agent lock", &lock);
    check_jvmti_error(jvmti, err, "create raw monitor");
    /* Start monitor list */
    monitor_count = 0;
    monitor_list  = (Monitor**)malloc((int)sizeof(Monitor*));
}
Example #4
0
static bool display_log_line(int fd)
{
	log_level level;
	wchar_t *module, *msg;

	level = ctl_recv_int(fd);
	if (check_error()) {
		return false;
	}

	module = ctl_recv_wchars(fd, NULL);
	if (!module) {
		return false;
	}

	msg = ctl_recv_wchars(fd, NULL);
	if (!msg) {
		return false;
	}

	stdout_message(level, module, msg);

	/* Force a fflush in case with are redirected to a file */
	fflush(stdout);

	free(module);
	free(msg);

	return true;
}
Example #5
0
/* Callback for JVMTI_EVENT_VM_INIT */
static void JNICALL
cbVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
    enter_critical_section(jvmti);
    {
        char  tname[MAX_THREAD_NAME_LENGTH];
        static jvmtiEvent events[] =
        { JVMTI_EVENT_THREAD_START, JVMTI_EVENT_THREAD_END };
        int        i;

        /* The VM has started. */
        get_thread_name(jvmti, thread, tname, sizeof(tname));
        stdout_message("VMInit %s\n", tname);

        /* The VM is now initialized, at this time we make our requests
         *   for additional events.
         */

        for( i=0; i < (int)(sizeof(events)/sizeof(jvmtiEvent)); i++) {
            jvmtiError error;

            /* Setup event  notification modes */
            error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
                    events[i], (jthread)NULL);
            check_jvmti_error(jvmti, error, "Cannot set event notification");
        }

    }
    exit_critical_section(jvmti);
}
Example #6
0
void Agent::vm_death(jvmtiEnv *jvmti, JNIEnv *env)
{
    /* Delete all Monitors we allocated */
    for ( int i = 0; i < (int)monitor_count; i++ ) {
        delete monitor_list[i];
    }
    free(monitor_list);
    /* Print death message */
    stdout_message("VMDeath...\n");
}
Example #7
0
/* Callback for JVMTI_EVENT_VM_INIT */
static void JNICALL
vm_init(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
    jvmtiError err;

    stdout_message("VMInit...\n");

    err = (*jvmti)->RunAgentThread(jvmti, alloc_thread(env), &worker, NULL,
        JVMTI_THREAD_MAX_PRIORITY);
    check_jvmti_error(jvmti, err, "running agent thread");
}
/* Create major.minor.micro version string */
static void
version_check(jint cver, jint rver)
{
    jint cmajor, cminor, cmicro;
    jint rmajor, rminor, rmicro;

    cmajor = (cver & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR;
    cminor = (cver & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR;
    cmicro = (cver & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO;
    rmajor = (rver & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR;
    rminor = (rver & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR;
    rmicro = (rver & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO;
    stdout_message("Compile Time JVMTI Version: %d.%d.%d (0x%08x)\n",
                        cmajor, cminor, cmicro, cver);
    stdout_message("Run Time JVMTI Version: %d.%d.%d (0x%08x)\n",
                        rmajor, rminor, rmicro, rver);
    if ( (cmajor > rmajor) || (cmajor == rmajor && cminor > rminor) ) {
        fatal_error(
            "ERROR: Compile Time JVMTI and Run Time JVMTI are incompatible\n");
    }
}
Example #9
0
/* Callback for JVMTI_EVENT_THREAD_END */
static void JNICALL
cbThreadEnd(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
    enter_critical_section(jvmti); {
        /* It's possible we get here right after VmDeath event, be careful */
        if ( !gdata->vm_is_dead ) {
            char  tname[MAX_THREAD_NAME_LENGTH];

            get_thread_name(jvmti, thread, tname, sizeof(tname));
            stdout_message("ThreadEnd %s\n", tname);
        }
    } exit_critical_section(jvmti);
}
Example #10
0
/* Callback for JVMTI_EVENT_GARBAGE_COLLECTION_FINISH */
static void JNICALL
gc_finish(jvmtiEnv* jvmti_env)
{
    jvmtiError err;

    stdout_message("GarbageCollectionFinish...\n");

    err = (*jvmti)->RawMonitorEnter(jvmti, lock);
    check_jvmti_error(jvmti, err, "raw monitor enter");
    gc_count++;
    err = (*jvmti)->RawMonitorNotify(jvmti, lock);
    check_jvmti_error(jvmti, err, "raw monitor notify");
    err = (*jvmti)->RawMonitorExit(jvmti, lock);
    check_jvmti_error(jvmti, err, "raw monitor exit");
}
Example #11
0
void Agent::vm_death(jvmtiEnv *jvmti, JNIEnv *env) 
{
    jvmtiError err;
    
    /* Delete all Monitors we allocated */
    for ( int i = 0; i < (int)monitor_count; i++ ) {
	delete monitor_list[i];
    }
    free(monitor_list);
    /* Destroy the Monitor lock to use */
    err = jvmti->DestroyRawMonitor(lock);
    check_jvmti_error(jvmti, err, "destroy raw monitor");
    /* Print death message */
    stdout_message("VMDeath...\n");
}
/* Parse the options for this heapTracker agent */
static void
parse_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));
    }
}
Example #13
0
/* Callback for JVMTI_EVENT_VM_START */
static void JNICALL
cbVMStart(jvmtiEnv *jvmti, JNIEnv *env)
{
    enter_critical_section(jvmti);
    {
        jclass   klass;
        jfieldID field;
        int      rc;

        /* Java Native Methods for class */
        static JNINativeMethod registry[2] = {
            {   STRING(MTRACE_native_entry), "(Ljava/lang/Object;II)V",
                (void*)&MTRACE_native_entry
            },
            {   STRING(MTRACE_native_exit),  "(Ljava/lang/Object;II)V",
                (void*)&MTRACE_native_exit
            }
        };

        /* The VM has started. */
        stdout_message("VMStart\n");

        /* Register Natives for class whose methods we use */
        klass = (*env)->FindClass(env, STRING(MTRACE_class));
        if ( klass == NULL ) {
            fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
                        STRING(MTRACE_class));
        }
        rc = (*env)->RegisterNatives(env, klass, registry, 2);
        if ( rc != 0 ) {
            fatal_error("ERROR: JNI: Cannot register native methods for %s\n",
                        STRING(MTRACE_class));
        }

        /* Engage calls. */
        field = (*env)->GetStaticFieldID(env, klass, STRING(MTRACE_engaged), "I");
        if ( field == NULL ) {
            fatal_error("ERROR: JNI: Cannot get field from %s\n",
                        STRING(MTRACE_class));
        }
        (*env)->SetStaticIntField(env, klass, field, 1);

        /* Indicate VM has started */
        gdata->vm_is_started = JNI_TRUE;

    }
    exit_critical_section(jvmti);
}
Example #14
0
/* Given a jvmtiEnv* and jthread, find the Thread instance */
Thread *
Agent::get_thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
    jvmtiError err;
    Thread    *t;

    /* This should always be in the Thread Local Storage */
    t = NULL;
    err = jvmti->GetThreadLocalStorage(thread, (void**)&t);
    check_jvmti_error(jvmti, err, "get thread local storage");
    if ( t == NULL ) {
        /* This jthread has never been seen before? */
        stdout_message("WARNING: Never before seen jthread?\n");
        t = new Thread(jvmti, env, thread);
        err = jvmti->SetThreadLocalStorage(thread, (const void*)t);
        check_jvmti_error(jvmti, err, "set thread local storage");
    }
    return t;
}
Example #15
0
/* Callback for JVMTI_EVENT_VM_DEATH */
static void JNICALL
cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env)
{
    enter_critical_section(jvmti);
    {
        jclass   klass;
        jfieldID field;

        /* The VM has died. */
        stdout_message("VMDeath\n");

        /* Disengage calls in MINST_class. */
        klass = (*env)->FindClass(env, STRING(MINST_class));
        if ( klass == NULL ) {
            fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
                        STRING(MINST_class));
        }
        field = (*env)->GetStaticFieldID(env, klass, STRING(MINST_engaged), "I");
        if ( field == NULL ) {
            fatal_error("ERROR: JNI: Cannot get field from %s\n",
                        STRING(MINST_class));
        }
        (*env)->SetStaticIntField(env, klass, field, -1);

        /* The critical section here is important to hold back the VM death
         *    until all other callbacks have completed.
         */

        /* Since this critical section could be holding up other threads
         *   in other event callbacks, we need to indicate that the VM is
         *   dead so that the other callbacks can short circuit their work.
         *   We don't expect any further events after VmDeath but we do need
         *   to be careful that existing threads might be in our own agent
         *   callback code.
         */
        gdata->vm_is_dead = JNI_TRUE;

    }
    exit_critical_section(jvmti);

}
/* Print the information */
static void
printTraceInfo(jvmtiEnv *jvmti, int index, TraceInfo* tinfo)
{
    if ( tinfo == NULL ) {
        fatal_error("%d: NULL ENTRY ERROR\n", index);
        return;
    }
    
    stdout_message("%2d: %7d bytes %5d objects %5d live %s",
                index, (int)tinfo->totalSpace, tinfo->totalCount, 
                tinfo->useCount, flavorDesc[tinfo->trace.flavor]);
    
    if (  tinfo->trace.nframes > 0 ) {
        int i;
        int fcount;

        fcount = 0;
        stdout_message(" stack=(");
        for ( i = 0 ; i < tinfo->trace.nframes ; i++ ) {
            char buf[4096];

            frameToString(jvmti, buf, (int)sizeof(buf), tinfo->trace.frames+i);
            if ( buf[0] == 0 ) {
                continue; /* Skip the ones that are from Tracker class */
            }
            fcount++;
            stdout_message("%s", buf);
            if ( i < (tinfo->trace.nframes-1) ) {
                stdout_message(",");
            }
        }
        stdout_message(") nframes=%d\n", fcount);
    } else {
        stdout_message(" stack=<empty>\n");
    }
}
Example #17
0
Monitor::~Monitor() 
{
    stdout_message("Monitor %s summary: %d contends, %d waits, %d timeouts\n",
	name, contends, waits, timeouts);
}
Example #18
0
Agent::~Agent()
{
    stdout_message("Agent reclaimed..\n");
}
Example #19
0
Thread::~Thread()
{
    /* Send out summary message */
    stdout_message("Thread %s summary: %d waits plus %d contended\n",
        name, waits, contends);
}
/* Callback for JVMTI_EVENT_DATA_DUMP_REQUEST (Ctrl-\ or at exit) */
static void JNICALL
dataDumpRequest(jvmtiEnv *jvmti)
{
    enterAgentMonitor(jvmti); {
        if ( !gdata->vmDeathCalled && !gdata->dumpInProgress ) {
            jvmtiHeapCallbacks heapCallbacks;
            ClassDetails      *details;
            jvmtiError         err;
            jclass            *classes;
            jint               totalCount;
            jint               count;
            jint               i;

            gdata->dumpInProgress = JNI_TRUE;

            /* Get all the loaded classes */
            err = (*jvmti)->GetLoadedClasses(jvmti, &count, &classes);
            check_jvmti_error(jvmti, err, "get loaded classes");

            /* Setup an area to hold details about these classes */
            details = (ClassDetails*)calloc(sizeof(ClassDetails), count);
            if ( details == NULL ) {
                fatal_error("ERROR: Ran out of malloc space\n");
            }
            for ( i = 0 ; i < count ; i++ ) {
                char *sig;

                /* Get and save the class signature */
                err = (*jvmti)->GetClassSignature(jvmti, classes[i], &sig, NULL);
                check_jvmti_error(jvmti, err, "get class signature");
                if ( sig == NULL ) {
                    fatal_error("ERROR: No class signature found\n");
                }
                details[i].signature = strdup(sig);
                deallocate(jvmti, sig);

                /* Tag this jclass */
                err = (*jvmti)->SetTag(jvmti, classes[i],
                                    (jlong)(ptrdiff_t)(void*)(&details[i]));
                check_jvmti_error(jvmti, err, "set object tag");
            }

            /* Iterate through the heap and count up uses of jclass */
            (void)memset(&heapCallbacks, 0, sizeof(heapCallbacks));
            heapCallbacks.heap_iteration_callback = &cbHeapObject;
            totalCount = 0;
            err = (*jvmti)->IterateThroughHeap(jvmti,
                       JVMTI_HEAP_FILTER_CLASS_UNTAGGED, NULL,
                       &heapCallbacks, (const void *)&totalCount);
            check_jvmti_error(jvmti, err, "iterate through heap");

            /* Remove tags */
            for ( i = 0 ; i < count ; i++ ) {
                /* Un-Tag this jclass */
                err = (*jvmti)->SetTag(jvmti, classes[i], (jlong)0);
                check_jvmti_error(jvmti, err, "set object tag");
            }

            /* Sort details by space used */
            qsort(details, count, sizeof(ClassDetails), &compareDetails);

            /* Print out sorted table */
            stdout_message("Heap View, Total of %d objects found.\n\n",
                         totalCount);

            stdout_message("Space      Count      Class Signature\n");
            stdout_message("---------- ---------- ----------------------\n");

            for ( i = 0 ; i < count ; i++ ) {
                if ( details[i].space == 0 || i > 20 ) {
                    break;
                }
                stdout_message("%10d %10d %s\n",
                    details[i].space, details[i].count, details[i].signature);
            }
            stdout_message("---------- ---------- ----------------------\n\n");

            /* Free up all allocated space */
            deallocate(jvmti, classes);
            for ( i = 0 ; i < count ; i++ ) {
                if ( details[i].signature != NULL ) {
                    free(details[i].signature);
                }
            }
            free(details);

            gdata->dumpInProgress = JNI_FALSE;
        }
    } exitAgentMonitor(jvmti);
}
Example #21
0
/* Callback for JVMTI_EVENT_VM_DEATH */
static void JNICALL
cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env)
{
    enter_critical_section(jvmti);
    {
        jclass   klass;
        jfieldID field;

        /* The VM has died. */
        stdout_message("VMDeath\n");

        /* Disengage calls in MTRACE_class. */
        klass = (*env)->FindClass(env, STRING(MTRACE_class));
        if ( klass == NULL ) {
            fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
                        STRING(MTRACE_class));
        }
        field = (*env)->GetStaticFieldID(env, klass, STRING(MTRACE_engaged), "I");
        if ( field == NULL ) {
            fatal_error("ERROR: JNI: Cannot get field from %s\n",
                        STRING(MTRACE_class));
        }
        (*env)->SetStaticIntField(env, klass, field, 0);

        /* The critical section here is important to hold back the VM death
         *    until all other callbacks have completed.
         */

        /* Since this critical section could be holding up other threads
         *   in other event callbacks, we need to indicate that the VM is
         *   dead so that the other callbacks can short circuit their work.
         *   We don't expect any further events after VmDeath but we do need
         *   to be careful that existing threads might be in our own agent
         *   callback code.
         */
        gdata->vm_is_dead = JNI_TRUE;

        /* Dump out stats */
        stdout_message("Begin Class Stats\n");
        if ( gdata->ccount > 0 ) {
            int cnum;

            /* Sort table (in place) by number of method calls into class. */
            /*  Note: Do not use this table after this qsort! */
            qsort(gdata->classes, gdata->ccount, sizeof(ClassInfo),
                  &class_compar);

            /* Dump out gdata->max_count most called classes */
            for ( cnum=gdata->ccount-1 ;
                    cnum >= 0 && cnum >= gdata->ccount - gdata->max_count;
                    cnum-- ) {
                ClassInfo *cp;
                int        mnum;

                cp = gdata->classes + cnum;
                stdout_message("Class %s %d calls\n", cp->name, cp->calls);
                if ( cp->calls==0 ) continue;

                /* Sort method table (in place) by number of method calls. */
                /*  Note: Do not use this table after this qsort! */
                qsort(cp->methods, cp->mcount, sizeof(MethodInfo),
                      &method_compar);
                for ( mnum=cp->mcount-1 ; mnum >= 0 ; mnum-- ) {
                    MethodInfo *mp;

                    mp = cp->methods + mnum;
                    if ( mp->calls==0 ) continue;
                    stdout_message("\tMethod %s %s %d calls %d returns\n",
                                   mp->name, mp->signature, mp->calls, mp->returns);
                }
            }
        }
        stdout_message("End Class Stats\n");
        (void)fflush(stdout);

    }
    exit_critical_section(jvmti);

}
/* Callback for JVMTI_EVENT_VM_DEATH */
static void JNICALL
cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env)
{
    jvmtiHeapCallbacks heapCallbacks;
    jvmtiError         error;

    /* These are purposely done outside the critical section */

    /* Force garbage collection now so we get our ObjectFree calls */
    error = (*jvmti)->ForceGarbageCollection(jvmti);
    check_jvmti_error(jvmti, error, "Cannot force garbage collection");
    
    /* Iterate through heap and find all objects */
    (void)memset(&heapCallbacks, 0, sizeof(heapCallbacks));
    heapCallbacks.heap_iteration_callback = &cbObjectSpaceCounter;
    error = (*jvmti)->IterateThroughHeap(jvmti, 0, NULL, &heapCallbacks, NULL);
    check_jvmti_error(jvmti, error, "Cannot iterate through heap");

    /* Process VM Death */
    enterCriticalSection(jvmti); {
        jclass              klass;
        jfieldID            field;
        jvmtiEventCallbacks callbacks;

        /* Disengage calls in HEAP_TRACKER_class. */
        klass = (*env)->FindClass(env, STRING(HEAP_TRACKER_class));
        if ( klass == NULL ) {
            fatal_error("ERROR: JNI: Cannot find %s with FindClass\n", 
                        STRING(HEAP_TRACKER_class));
        }
        field = (*env)->GetStaticFieldID(env, klass, STRING(HEAP_TRACKER_engaged), "I");
        if ( field == NULL ) {
            fatal_error("ERROR: JNI: Cannot get field from %s\n", 
                        STRING(HEAP_TRACKER_class));
        }
        (*env)->SetStaticIntField(env, klass, field, 0);

        /* The critical section here is important to hold back the VM death
         *    until all other callbacks have completed.
         */

        /* Clear out all callbacks. */
        (void)memset(&callbacks,0, sizeof(callbacks));
        error = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, 
                                            (jint)sizeof(callbacks));
        check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks");
        
        /* Since this critical section could be holding up other threads
         *   in other event callbacks, we need to indicate that the VM is
         *   dead so that the other callbacks can short circuit their work.
         *   We don't expect an further events after VmDeath but we do need
         *   to be careful that existing threads might be in our own agent
         *   callback code.
         */
        gdata->vmDead = JNI_TRUE;

        /* Dump all objects */
        if ( gdata->traceInfoCount > 0 ) {
            TraceInfo **list;
            int         count;
            int         i;
           
            stdout_message("Dumping heap trace information\n");

            /* 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);
        
}  
Example #23
0
/* Parse the options for this mtrace agent */
static void
parse_agent_options(char *options)
{
    char token[MAX_TOKEN_LENGTH];
    char *next;

    gdata->max_count = 10; /* Default max=n */

    /* Parse options and set flags in gdata */
    if ( options==NULL ) {
        return;
    }

    /* Get the first token from the options string. */
    next = get_token(options, ",=", token, 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 mtrace JVMTI demo agent\n");
            stdout_message("\n");
            stdout_message(" java -agent:mtrace[=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 max=n\t\t Only list top n classes\n");
            stdout_message("\t include=item\t\t Only these classes/methods\n");
            stdout_message("\t exclude=item\t\t Exclude these classes/methods\n");
            stdout_message("\n");
            stdout_message("item\t Qualified class and/or method names\n");
            stdout_message("\t\t e.g. (*.<init>;Foobar.method;sun.*)\n");
            stdout_message("\n");
            exit(0);
        } else if ( strcmp(token,"max")==0 ) {
            char number[MAX_TOKEN_LENGTH];

            /* Get the numeric option */
            next = get_token(next, ",=", number, (int)sizeof(number));
            /* Check for token scan error */
            if ( next==NULL ) {
                fatal_error("ERROR: max=n option error\n");
            }
            /* Save numeric value */
            gdata->max_count = atoi(number);
        } else if ( strcmp(token,"include")==0 ) {
            int   used;
            int   maxlen;

            maxlen = MAX_METHOD_NAME_LENGTH;
            if ( gdata->include == NULL ) {
                gdata->include = (char*)calloc(maxlen+1, 1);
                used = 0;
            } else {
                used  = (int)strlen(gdata->include);
                gdata->include[used++] = ',';
                gdata->include[used] = 0;
                gdata->include = (char*)
                                 realloc((void*)gdata->include, used+maxlen+1);
            }
            if ( gdata->include == NULL ) {
                fatal_error("ERROR: Out of malloc memory\n");
            }
            /* Add this item to the list */
            next = get_token(next, ",=", gdata->include+used, maxlen);
            /* Check for token scan error */
            if ( next==NULL ) {
                fatal_error("ERROR: include option error\n");
            }
        } else if ( strcmp(token,"exclude")==0 ) {
            int   used;
            int   maxlen;

            maxlen = MAX_METHOD_NAME_LENGTH;
            if ( gdata->exclude == NULL ) {
                gdata->exclude = (char*)calloc(maxlen+1, 1);
                used = 0;
            } else {
                used  = (int)strlen(gdata->exclude);
                gdata->exclude[used++] = ',';
                gdata->exclude[used] = 0;
                gdata->exclude = (char*)
                                 realloc((void*)gdata->exclude, used+maxlen+1);
            }
            if ( gdata->exclude == NULL ) {
                fatal_error("ERROR: Out of malloc memory\n");
            }
            /* Add this item to the list */
            next = get_token(next, ",=", gdata->exclude+used, maxlen);
            /* Check for token scan error */
            if ( next==NULL ) {
                fatal_error("ERROR: exclude option error\n");
            }
        } 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, sizeof(token));
    }
}
Example #24
0
/* Callback for JVMTI_EVENT_GARBAGE_COLLECTION_START */
static void JNICALL
gc_start(jvmtiEnv* jvmti_env)
{
    stdout_message("GarbageCollectionStart...\n");
}