1 /*
   2  * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  *
   8  *   - Redistributions of source code must retain the above copyright
   9  *     notice, this list of conditions and the following disclaimer.
  10  *
  11  *   - Redistributions in binary form must reproduce the above copyright
  12  *     notice, this list of conditions and the following disclaimer in the
  13  *     documentation and/or other materials provided with the distribution.
  14  *
  15  *   - Neither the name of Oracle nor the names of its
  16  *     contributors may be used to endorse or promote products derived
  17  *     from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 /*
  33  * This source code is provided to illustrate the usage of a given feature
  34  * or technique and has been deliberately simplified. Additional steps
  35  * required for a production-quality application, such as security checks,
  36  * input validation and proper error handling, might not be present in
  37  * this sample code.
  38  */
  39 
  40 
  41 #include "stdlib.h"
  42 
  43 #include "mtrace.h"
  44 #include "java_crw_demo.h"
  45 
  46 
  47 /* ------------------------------------------------------------------- */
  48 /* Some constant maximum sizes */
  49 
  50 #define MAX_TOKEN_LENGTH        16
  51 #define MAX_THREAD_NAME_LENGTH  512
  52 #define MAX_METHOD_NAME_LENGTH  1024
  53 
  54 /* Some constant names that tie to Java class/method names.
  55  *    We assume the Java class whose static methods we will be calling
  56  *    looks like:
  57  *
  58  * public class Mtrace {
  59  *     private static int engaged;
  60  *     private static native void _method_entry(Object thr, int cnum, int mnum);
  61  *     public static void method_entry(int cnum, int mnum)
  62  *     {
  63  *         if ( engaged != 0 ) {
  64  *             _method_entry(Thread.currentThread(), cnum, mnum);
  65  *         }
  66  *     }
  67  *     private static native void _method_exit(Object thr, int cnum, int mnum);
  68  *     public static void method_exit(int cnum, int mnum)
  69  *     {
  70  *         if ( engaged != 0 ) {
  71  *             _method_exit(Thread.currentThread(), cnum, mnum);
  72  *         }
  73  *     }
  74  * }
  75  *
  76  *    The engaged field allows us to inject all classes (even system classes)
  77  *    and delay the actual calls to the native code until the VM has reached
  78  *    a safe time to call native methods (Past the JVMTI VM_START event).
  79  *
  80  */
  81 
  82 #define MTRACE_class        Mtrace          /* Name of class we are using */
  83 #define MTRACE_entry        method_entry    /* Name of java entry method */
  84 #define MTRACE_exit         method_exit     /* Name of java exit method */
  85 #define MTRACE_native_entry _method_entry   /* Name of java entry native */
  86 #define MTRACE_native_exit  _method_exit    /* Name of java exit native */
  87 #define MTRACE_engaged      engaged         /* Name of java static field */
  88 
  89 /* C macros to create strings from tokens */
  90 #define _STRING(s) #s
  91 #define STRING(s) _STRING(s)
  92 
  93 /* ------------------------------------------------------------------- */
  94 
  95 /* Data structure to hold method and class information in agent */
  96 
  97 typedef struct MethodInfo {
  98     const char *name;          /* Method name */
  99     const char *signature;     /* Method signature */
 100     int         calls;         /* Method call count */
 101     int         returns;       /* Method return count */
 102 } MethodInfo;
 103 
 104 typedef struct ClassInfo {
 105     const char *name;          /* Class name */
 106     int         mcount;        /* Method count */
 107     MethodInfo *methods;       /* Method information */
 108     int         calls;         /* Method call count for this class */
 109 } ClassInfo;
 110 
 111 /* Global agent data structure */
 112 
 113 typedef struct {
 114     /* JVMTI Environment */
 115     jvmtiEnv      *jvmti;
 116     jboolean       vm_is_dead;
 117     jboolean       vm_is_started;
 118     /* Data access Lock */
 119     jrawMonitorID  lock;
 120     /* Options */
 121     char           *include;
 122     char           *exclude;
 123     int             max_count;
 124     /* ClassInfo Table */
 125     ClassInfo      *classes;
 126     jint            ccount;
 127 } GlobalAgentData;
 128 
 129 static GlobalAgentData *gdata;
 130 
 131 /* Enter a critical section by doing a JVMTI Raw Monitor Enter */
 132 static void
 133 enter_critical_section(jvmtiEnv *jvmti)
 134 {
 135     jvmtiError error;
 136 
 137     error = (*jvmti)->RawMonitorEnter(jvmti, gdata->lock);
 138     check_jvmti_error(jvmti, error, "Cannot enter with raw monitor");
 139 }
 140 
 141 /* Exit a critical section by doing a JVMTI Raw Monitor Exit */
 142 static void
 143 exit_critical_section(jvmtiEnv *jvmti)
 144 {
 145     jvmtiError error;
 146 
 147     error = (*jvmti)->RawMonitorExit(jvmti, gdata->lock);
 148     check_jvmti_error(jvmti, error, "Cannot exit with raw monitor");
 149 }
 150 
 151 /* Get a name for a jthread */
 152 static void
 153 get_thread_name(jvmtiEnv *jvmti, jthread thread, char *tname, int maxlen)
 154 {
 155     jvmtiThreadInfo info;
 156     jvmtiError      error;
 157 
 158     /* Make sure the stack variables are garbage free */
 159     (void)memset(&info,0, sizeof(info));
 160 
 161     /* Assume the name is unknown for now */
 162     (void)strcpy(tname, "Unknown");
 163 
 164     /* Get the thread information, which includes the name */
 165     error = (*jvmti)->GetThreadInfo(jvmti, thread, &info);
 166     check_jvmti_error(jvmti, error, "Cannot get thread info");
 167 
 168     /* The thread might not have a name, be careful here. */
 169     if ( info.name != NULL ) {
 170         int len;
 171 
 172         /* Copy the thread name into tname if it will fit */
 173         len = (int)strlen(info.name);
 174         if ( len < maxlen ) {
 175             (void)strcpy(tname, info.name);
 176         }
 177 
 178         /* Every string allocated by JVMTI needs to be freed */
 179         deallocate(jvmti, (void*)info.name);
 180     }
 181 }
 182 
 183 /* Qsort class compare routine */
 184 static int
 185 class_compar(const void *e1, const void *e2)
 186 {
 187     ClassInfo *c1 = (ClassInfo*)e1;
 188     ClassInfo *c2 = (ClassInfo*)e2;
 189     if ( c1->calls > c2->calls ) return  1;
 190     if ( c1->calls < c2->calls ) return -1;
 191     return 0;
 192 }
 193 
 194 /* Qsort method compare routine */
 195 static int
 196 method_compar(const void *e1, const void *e2)
 197 {
 198     MethodInfo *m1 = (MethodInfo*)e1;
 199     MethodInfo *m2 = (MethodInfo*)e2;
 200     if ( m1->calls > m2->calls ) return  1;
 201     if ( m1->calls < m2->calls ) return -1;
 202     return 0;
 203 }
 204 
 205 /* Callback from java_crw_demo() that gives us mnum mappings */
 206 static void
 207 mnum_callbacks(unsigned cnum, const char **names, const char**sigs, int mcount)
 208 {
 209     ClassInfo  *cp;
 210     int         mnum;
 211 
 212     if ( cnum >= (unsigned)gdata->ccount ) {
 213         fatal_error("ERROR: Class number out of range\n");
 214     }
 215     if ( mcount == 0 ) {
 216         return;
 217     }
 218 
 219     cp           = gdata->classes + (int)cnum;
 220     cp->calls    = 0;
 221     cp->mcount   = mcount;
 222     cp->methods  = (MethodInfo*)calloc(mcount, sizeof(MethodInfo));
 223     if ( cp->methods == NULL ) {
 224         fatal_error("ERROR: Out of malloc memory\n");
 225     }
 226 
 227     for ( mnum = 0 ; mnum < mcount ; mnum++ ) {
 228         MethodInfo *mp;
 229 
 230         mp            = cp->methods + mnum;
 231         mp->name      = (const char *)strdup(names[mnum]);
 232         if ( mp->name == NULL ) {
 233             fatal_error("ERROR: Out of malloc memory\n");
 234         }
 235         mp->signature = (const char *)strdup(sigs[mnum]);
 236         if ( mp->signature == NULL ) {
 237             fatal_error("ERROR: Out of malloc memory\n");
 238         }
 239     }
 240 }
 241 
 242 /* Java Native Method for entry */
 243 static void
 244 MTRACE_native_entry(JNIEnv *env, jclass klass, jobject thread, jint cnum, jint mnum)
 245 {
 246     enter_critical_section(gdata->jvmti); {
 247         /* It's possible we get here right after VmDeath event, be careful */
 248         if ( !gdata->vm_is_dead ) {
 249             ClassInfo  *cp;
 250             MethodInfo *mp;
 251 
 252             if ( cnum >= gdata->ccount ) {
 253                 fatal_error("ERROR: Class number out of range\n");
 254             }
 255             cp = gdata->classes + cnum;
 256             if ( mnum >= cp->mcount ) {
 257                 fatal_error("ERROR: Method number out of range\n");
 258             }
 259             mp = cp->methods + mnum;
 260             if ( interested((char*)cp->name, (char*)mp->name,
 261                             gdata->include, gdata->exclude)  ) {
 262                 mp->calls++;
 263                 cp->calls++;
 264             }
 265         }
 266     } exit_critical_section(gdata->jvmti);
 267 }
 268 
 269 /* Java Native Method for exit */
 270 static void
 271 MTRACE_native_exit(JNIEnv *env, jclass klass, jobject thread, jint cnum, jint mnum)
 272 {
 273     enter_critical_section(gdata->jvmti); {
 274         /* It's possible we get here right after VmDeath event, be careful */
 275         if ( !gdata->vm_is_dead ) {
 276             ClassInfo  *cp;
 277             MethodInfo *mp;
 278 
 279             if ( cnum >= gdata->ccount ) {
 280                 fatal_error("ERROR: Class number out of range\n");
 281             }
 282             cp = gdata->classes + cnum;
 283             if ( mnum >= cp->mcount ) {
 284                 fatal_error("ERROR: Method number out of range\n");
 285             }
 286             mp = cp->methods + mnum;
 287             if ( interested((char*)cp->name, (char*)mp->name,
 288                             gdata->include, gdata->exclude)  ) {
 289                 mp->returns++;
 290             }
 291         }
 292     } exit_critical_section(gdata->jvmti);
 293 }
 294 
 295 /* Callback for JVMTI_EVENT_VM_START */
 296 static void JNICALL
 297 cbVMStart(jvmtiEnv *jvmti, JNIEnv *env)
 298 {
 299     enter_critical_section(jvmti); {
 300         jclass   klass;
 301         jfieldID field;
 302         int      rc;
 303 
 304         /* Java Native Methods for class */
 305         static JNINativeMethod registry[2] = {
 306             {STRING(MTRACE_native_entry), "(Ljava/lang/Object;II)V",
 307                 (void*)&MTRACE_native_entry},
 308             {STRING(MTRACE_native_exit),  "(Ljava/lang/Object;II)V",
 309                 (void*)&MTRACE_native_exit}
 310         };
 311 
 312         /* The VM has started. */
 313         stdout_message("VMStart\n");
 314 
 315         /* Register Natives for class whose methods we use */
 316         klass = (*env)->FindClass(env, STRING(MTRACE_class));
 317         if ( klass == NULL ) {
 318             fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
 319                         STRING(MTRACE_class));
 320         }
 321         rc = (*env)->RegisterNatives(env, klass, registry, 2);
 322         if ( rc != 0 ) {
 323             fatal_error("ERROR: JNI: Cannot register native methods for %s\n",
 324                         STRING(MTRACE_class));
 325         }
 326 
 327         /* Engage calls. */
 328         field = (*env)->GetStaticFieldID(env, klass, STRING(MTRACE_engaged), "I");
 329         if ( field == NULL ) {
 330             fatal_error("ERROR: JNI: Cannot get field from %s\n",
 331                         STRING(MTRACE_class));
 332         }
 333         (*env)->SetStaticIntField(env, klass, field, 1);
 334 
 335         /* Indicate VM has started */
 336         gdata->vm_is_started = JNI_TRUE;
 337 
 338     } exit_critical_section(jvmti);
 339 }
 340 
 341 /* Callback for JVMTI_EVENT_VM_INIT */
 342 static void JNICALL
 343 cbVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
 344 {
 345     enter_critical_section(jvmti); {
 346         char  tname[MAX_THREAD_NAME_LENGTH];
 347         static jvmtiEvent events[] =
 348                 { JVMTI_EVENT_THREAD_START, JVMTI_EVENT_THREAD_END };
 349         int        i;
 350 
 351         /* The VM has started. */
 352         get_thread_name(jvmti, thread, tname, sizeof(tname));
 353         stdout_message("VMInit %s\n", tname);
 354 
 355         /* The VM is now initialized, at this time we make our requests
 356          *   for additional events.
 357          */
 358 
 359         for( i=0; i < (int)(sizeof(events)/sizeof(jvmtiEvent)); i++) {
 360             jvmtiError error;
 361 
 362             /* Setup event  notification modes */
 363             error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
 364                                   events[i], (jthread)NULL);
 365             check_jvmti_error(jvmti, error, "Cannot set event notification");
 366         }
 367 
 368     } exit_critical_section(jvmti);
 369 }
 370 
 371 /* Callback for JVMTI_EVENT_VM_DEATH */
 372 static void JNICALL
 373 cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env)
 374 {
 375     enter_critical_section(jvmti); {
 376         jclass   klass;
 377         jfieldID field;
 378 
 379         /* The VM has died. */
 380         stdout_message("VMDeath\n");
 381 
 382         /* Disengage calls in MTRACE_class. */
 383         klass = (*env)->FindClass(env, STRING(MTRACE_class));
 384         if ( klass == NULL ) {
 385             fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
 386                         STRING(MTRACE_class));
 387         }
 388         field = (*env)->GetStaticFieldID(env, klass, STRING(MTRACE_engaged), "I");
 389         if ( field == NULL ) {
 390             fatal_error("ERROR: JNI: Cannot get field from %s\n",
 391                         STRING(MTRACE_class));
 392         }
 393         (*env)->SetStaticIntField(env, klass, field, 0);
 394 
 395         /* The critical section here is important to hold back the VM death
 396          *    until all other callbacks have completed.
 397          */
 398 
 399         /* Since this critical section could be holding up other threads
 400          *   in other event callbacks, we need to indicate that the VM is
 401          *   dead so that the other callbacks can short circuit their work.
 402          *   We don't expect any further events after VmDeath but we do need
 403          *   to be careful that existing threads might be in our own agent
 404          *   callback code.
 405          */
 406         gdata->vm_is_dead = JNI_TRUE;
 407 
 408         /* Dump out stats */
 409         stdout_message("Begin Class Stats\n");
 410         if ( gdata->ccount > 0 ) {
 411             int cnum;
 412 
 413             /* Sort table (in place) by number of method calls into class. */
 414             /*  Note: Do not use this table after this qsort! */
 415             qsort(gdata->classes, gdata->ccount, sizeof(ClassInfo),
 416                         &class_compar);
 417 
 418             /* Dump out gdata->max_count most called classes */
 419             for ( cnum=gdata->ccount-1 ;
 420                   cnum >= 0 && cnum >= gdata->ccount - gdata->max_count;
 421                   cnum-- ) {
 422                 ClassInfo *cp;
 423                 int        mnum;
 424 
 425                 cp = gdata->classes + cnum;
 426                 stdout_message("Class %s %d calls\n", cp->name, cp->calls);
 427                 if ( cp->calls==0 ) continue;
 428 
 429                 /* Sort method table (in place) by number of method calls. */
 430                 /*  Note: Do not use this table after this qsort! */
 431                 qsort(cp->methods, cp->mcount, sizeof(MethodInfo),
 432                             &method_compar);
 433                 for ( mnum=cp->mcount-1 ; mnum >= 0 ; mnum-- ) {
 434                     MethodInfo *mp;
 435 
 436                     mp = cp->methods + mnum;
 437                     if ( mp->calls==0 ) continue;
 438                     stdout_message("\tMethod %s %s %d calls %d returns\n",
 439                         mp->name, mp->signature, mp->calls, mp->returns);
 440                 }
 441             }
 442         }
 443         stdout_message("End Class Stats\n");
 444         (void)fflush(stdout);
 445 
 446     } exit_critical_section(jvmti);
 447 
 448 }
 449 
 450 /* Callback for JVMTI_EVENT_THREAD_START */
 451 static void JNICALL
 452 cbThreadStart(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
 453 {
 454     enter_critical_section(jvmti); {
 455         /* It's possible we get here right after VmDeath event, be careful */
 456         if ( !gdata->vm_is_dead ) {
 457             char  tname[MAX_THREAD_NAME_LENGTH];
 458 
 459             get_thread_name(jvmti, thread, tname, sizeof(tname));
 460             stdout_message("ThreadStart %s\n", tname);
 461         }
 462     } exit_critical_section(jvmti);
 463 }
 464 
 465 /* Callback for JVMTI_EVENT_THREAD_END */
 466 static void JNICALL
 467 cbThreadEnd(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
 468 {
 469     enter_critical_section(jvmti); {
 470         /* It's possible we get here right after VmDeath event, be careful */
 471         if ( !gdata->vm_is_dead ) {
 472             char  tname[MAX_THREAD_NAME_LENGTH];
 473 
 474             get_thread_name(jvmti, thread, tname, sizeof(tname));
 475             stdout_message("ThreadEnd %s\n", tname);
 476         }
 477     } exit_critical_section(jvmti);
 478 }
 479 
 480 /* Callback for JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
 481 static void JNICALL
 482 cbClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv* env,
 483                 jclass class_being_redefined, jobject loader,
 484                 const char* name, jobject protection_domain,
 485                 jint class_data_len, const unsigned char* class_data,
 486                 jint* new_class_data_len, unsigned char** new_class_data)
 487 {
 488     enter_critical_section(jvmti); {
 489         /* It's possible we get here right after VmDeath event, be careful */
 490         if ( !gdata->vm_is_dead ) {
 491 
 492             const char *classname;
 493 
 494             /* Name could be NULL */
 495             if ( name == NULL ) {
 496                 classname = java_crw_demo_classname(class_data, class_data_len,
 497                         NULL);
 498                 if ( classname == NULL ) {
 499                     fatal_error("ERROR: No classname inside classfile\n");
 500                 }
 501             } else {
 502                 classname = strdup(name);
 503                 if ( classname == NULL ) {
 504                     fatal_error("ERROR: Out of malloc memory\n");
 505                 }
 506             }
 507 
 508             *new_class_data_len = 0;
 509             *new_class_data     = NULL;
 510 
 511             /* The tracker class itself? */
 512             if ( interested((char*)classname, "", gdata->include, gdata->exclude)
 513                   &&  strcmp(classname, STRING(MTRACE_class)) != 0 ) {
 514                 jint           cnum;
 515                 int            system_class;
 516                 unsigned char *new_image;
 517                 long           new_length;
 518                 ClassInfo     *cp;
 519 
 520                 /* Get unique number for every class file image loaded */
 521                 cnum = gdata->ccount++;
 522 
 523                 /* Save away class information */
 524                 if ( gdata->classes == NULL ) {
 525                     gdata->classes = (ClassInfo*)malloc(
 526                                 gdata->ccount*sizeof(ClassInfo));
 527                 } else {
 528                     gdata->classes = (ClassInfo*)
 529                                 realloc((void*)gdata->classes,
 530                                 gdata->ccount*sizeof(ClassInfo));
 531                 }
 532                 if ( gdata->classes == NULL ) {
 533                     fatal_error("ERROR: Out of malloc memory\n");
 534                 }
 535                 cp           = gdata->classes + cnum;
 536                 cp->name     = (const char *)strdup(classname);
 537                 if ( cp->name == NULL ) {
 538                     fatal_error("ERROR: Out of malloc memory\n");
 539                 }
 540                 cp->calls    = 0;
 541                 cp->mcount   = 0;
 542                 cp->methods  = NULL;
 543 
 544                 /* Is it a system class? If the class load is before VmStart
 545                  *   then we will consider it a system class that should
 546                  *   be treated carefully. (See java_crw_demo)
 547                  */
 548                 system_class = 0;
 549                 if ( !gdata->vm_is_started ) {
 550                     system_class = 1;
 551                 }
 552 
 553                 new_image = NULL;
 554                 new_length = 0;
 555 
 556                 /* Call the class file reader/write demo code */
 557                 java_crw_demo(cnum,
 558                     classname,
 559                     class_data,
 560                     class_data_len,
 561                     system_class,
 562                     STRING(MTRACE_class), "L" STRING(MTRACE_class) ";",
 563                     STRING(MTRACE_entry), "(II)V",
 564                     STRING(MTRACE_exit), "(II)V",
 565                     NULL, NULL,
 566                     NULL, NULL,
 567                     &new_image,
 568                     &new_length,
 569                     NULL,
 570                     &mnum_callbacks);
 571 
 572                 /* If we got back a new class image, return it back as "the"
 573                  *   new class image. This must be JVMTI Allocate space.
 574                  */
 575                 if ( new_length > 0 ) {
 576                     unsigned char *jvmti_space;
 577 
 578                     jvmti_space = (unsigned char *)allocate(jvmti, (jint)new_length);
 579                     (void)memcpy((void*)jvmti_space, (void*)new_image, (int)new_length);
 580                     *new_class_data_len = (jint)new_length;
 581                     *new_class_data     = jvmti_space; /* VM will deallocate */
 582                 }
 583 
 584                 /* Always free up the space we get from java_crw_demo() */
 585                 if ( new_image != NULL ) {
 586                     (void)free((void*)new_image); /* Free malloc() space with free() */
 587                 }
 588             }
 589             (void)free((void*)classname);
 590         }
 591     } exit_critical_section(jvmti);
 592 }
 593 
 594 /* Parse the options for this mtrace agent */
 595 static void
 596 parse_agent_options(char *options)
 597 {
 598     char token[MAX_TOKEN_LENGTH];
 599     char *next;
 600 
 601     gdata->max_count = 10; /* Default max=n */
 602 
 603     /* Parse options and set flags in gdata */
 604     if ( options==NULL ) {
 605         return;
 606     }
 607 
 608     /* Get the first token from the options string. */
 609     next = get_token(options, ",=", token, sizeof(token));
 610 
 611     /* While not at the end of the options string, process this option. */
 612     while ( next != NULL ) {
 613         if ( strcmp(token,"help")==0 ) {
 614             stdout_message("The mtrace JVMTI demo agent\n");
 615             stdout_message("\n");
 616             stdout_message(" java -agent:mtrace[=options] ...\n");
 617             stdout_message("\n");
 618             stdout_message("The options are comma separated:\n");
 619             stdout_message("\t help\t\t\t Print help information\n");
 620             stdout_message("\t max=n\t\t Only list top n classes\n");
 621             stdout_message("\t include=item\t\t Only these classes/methods\n");
 622             stdout_message("\t exclude=item\t\t Exclude these classes/methods\n");
 623             stdout_message("\n");
 624             stdout_message("item\t Qualified class and/or method names\n");
 625             stdout_message("\t\t e.g. (*.<init>;Foobar.method;sun.*)\n");
 626             stdout_message("\n");
 627             exit(0);
 628         } else if ( strcmp(token,"max")==0 ) {
 629             char number[MAX_TOKEN_LENGTH];
 630 
 631             /* Get the numeric option */
 632             next = get_token(next, ",=", number, (int)sizeof(number));
 633             /* Check for token scan error */
 634             if ( next==NULL ) {
 635                 fatal_error("ERROR: max=n option error\n");
 636             }
 637             /* Save numeric value */
 638             gdata->max_count = atoi(number);
 639         } else if ( strcmp(token,"include")==0 ) {
 640             int   used;
 641             int   maxlen;
 642 
 643             maxlen = MAX_METHOD_NAME_LENGTH;
 644             if ( gdata->include == NULL ) {
 645                 gdata->include = (char*)calloc(maxlen+1, 1);
 646                 used = 0;
 647             } else {
 648                 used  = (int)strlen(gdata->include);
 649                 gdata->include[used++] = ',';
 650                 gdata->include[used] = 0;
 651                 gdata->include = (char*)
 652                              realloc((void*)gdata->include, used+maxlen+1);
 653             }
 654             if ( gdata->include == NULL ) {
 655                 fatal_error("ERROR: Out of malloc memory\n");
 656             }
 657             /* Add this item to the list */
 658             next = get_token(next, ",=", gdata->include+used, maxlen);
 659             /* Check for token scan error */
 660             if ( next==NULL ) {
 661                 fatal_error("ERROR: include option error\n");
 662             }
 663         } else if ( strcmp(token,"exclude")==0 ) {
 664             int   used;
 665             int   maxlen;
 666 
 667             maxlen = MAX_METHOD_NAME_LENGTH;
 668             if ( gdata->exclude == NULL ) {
 669                 gdata->exclude = (char*)calloc(maxlen+1, 1);
 670                 used = 0;
 671             } else {
 672                 used  = (int)strlen(gdata->exclude);
 673                 gdata->exclude[used++] = ',';
 674                 gdata->exclude[used] = 0;
 675                 gdata->exclude = (char*)
 676                              realloc((void*)gdata->exclude, used+maxlen+1);
 677             }
 678             if ( gdata->exclude == NULL ) {
 679                 fatal_error("ERROR: Out of malloc memory\n");
 680             }
 681             /* Add this item to the list */
 682             next = get_token(next, ",=", gdata->exclude+used, maxlen);
 683             /* Check for token scan error */
 684             if ( next==NULL ) {
 685                 fatal_error("ERROR: exclude option error\n");
 686             }
 687         } else if ( token[0]!=0 ) {
 688             /* We got a non-empty token and we don't know what it is. */
 689             fatal_error("ERROR: Unknown option: %s\n", token);
 690         }
 691         /* Get the next token (returns NULL if there are no more) */
 692         next = get_token(next, ",=", token, sizeof(token));
 693     }
 694 }
 695 
 696 /* Agent_OnLoad: This is called immediately after the shared library is
 697  *   loaded. This is the first code executed.
 698  */
 699 JNIEXPORT jint JNICALL
 700 Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 701 {
 702     static GlobalAgentData data;
 703     jvmtiEnv              *jvmti;
 704     jvmtiError             error;
 705     jint                   res;
 706     jvmtiCapabilities      capabilities;
 707     jvmtiEventCallbacks    callbacks;
 708 
 709     /* Setup initial global agent data area
 710      *   Use of static/extern data should be handled carefully here.
 711      *   We need to make sure that we are able to cleanup after ourselves
 712      *     so anything allocated in this library needs to be freed in
 713      *     the Agent_OnUnload() function.
 714      */
 715     (void)memset((void*)&data, 0, sizeof(data));
 716     gdata = &data;
 717 
 718     /* First thing we need to do is get the jvmtiEnv* or JVMTI environment */
 719     res = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_1);
 720     if (res != JNI_OK) {
 721         /* This means that the VM was unable to obtain this version of the
 722          *   JVMTI interface, this is a fatal error.
 723          */
 724         fatal_error("ERROR: Unable to access JVMTI Version 1 (0x%x),"
 725                 " is your JDK a 5.0 or newer version?"
 726                 " JNIEnv's GetEnv() returned %d\n",
 727                JVMTI_VERSION_1, res);
 728     }
 729 
 730     /* Here we save the jvmtiEnv* for Agent_OnUnload(). */
 731     gdata->jvmti = jvmti;
 732 
 733     /* Parse any options supplied on java command line */
 734     parse_agent_options(options);
 735 
 736     /* Immediately after getting the jvmtiEnv* we need to ask for the
 737      *   capabilities this agent will need. In this case we need to make
 738      *   sure that we can get all class load hooks.
 739      */
 740     (void)memset(&capabilities,0, sizeof(capabilities));
 741     capabilities.can_generate_all_class_hook_events  = 1;
 742     error = (*jvmti)->AddCapabilities(jvmti, &capabilities);
 743     check_jvmti_error(jvmti, error, "Unable to get necessary JVMTI capabilities.");
 744 
 745     /* Next we need to provide the pointers to the callback functions to
 746      *   to this jvmtiEnv*
 747      */
 748     (void)memset(&callbacks,0, sizeof(callbacks));
 749     /* JVMTI_EVENT_VM_START */
 750     callbacks.VMStart           = &cbVMStart;
 751     /* JVMTI_EVENT_VM_INIT */
 752     callbacks.VMInit            = &cbVMInit;
 753     /* JVMTI_EVENT_VM_DEATH */
 754     callbacks.VMDeath           = &cbVMDeath;
 755     /* JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
 756     callbacks.ClassFileLoadHook = &cbClassFileLoadHook;
 757     /* JVMTI_EVENT_THREAD_START */
 758     callbacks.ThreadStart       = &cbThreadStart;
 759     /* JVMTI_EVENT_THREAD_END */
 760     callbacks.ThreadEnd         = &cbThreadEnd;
 761     error = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, (jint)sizeof(callbacks));
 762     check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks");
 763 
 764     /* At first the only initial events we are interested in are VM
 765      *   initialization, VM death, and Class File Loads.
 766      *   Once the VM is initialized we will request more events.
 767      */
 768     error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
 769                           JVMTI_EVENT_VM_START, (jthread)NULL);
 770     check_jvmti_error(jvmti, error, "Cannot set event notification");
 771     error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
 772                           JVMTI_EVENT_VM_INIT, (jthread)NULL);
 773     check_jvmti_error(jvmti, error, "Cannot set event notification");
 774     error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
 775                           JVMTI_EVENT_VM_DEATH, (jthread)NULL);
 776     check_jvmti_error(jvmti, error, "Cannot set event notification");
 777     error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
 778                           JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, (jthread)NULL);
 779     check_jvmti_error(jvmti, error, "Cannot set event notification");
 780 
 781     /* Here we create a raw monitor for our use in this agent to
 782      *   protect critical sections of code.
 783      */
 784     error = (*jvmti)->CreateRawMonitor(jvmti, "agent data", &(gdata->lock));
 785     check_jvmti_error(jvmti, error, "Cannot create raw monitor");
 786 
 787     /* Add demo jar file to boot classpath */
 788     add_demo_jar_to_bootclasspath(jvmti, "mtrace");
 789 
 790     /* We return JNI_OK to signify success */
 791     return JNI_OK;
 792 }
 793 
 794 /* Agent_OnUnload: This is called immediately before the shared library is
 795  *   unloaded. This is the last code executed.
 796  */
 797 JNIEXPORT void JNICALL
 798 Agent_OnUnload(JavaVM *vm)
 799 {
 800     /* Make sure all malloc/calloc/strdup space is freed */
 801     if ( gdata->include != NULL ) {
 802         (void)free((void*)gdata->include);
 803         gdata->include = NULL;
 804     }
 805     if ( gdata->exclude != NULL ) {
 806         (void)free((void*)gdata->exclude);
 807         gdata->exclude = NULL;
 808     }
 809     if ( gdata->classes != NULL ) {
 810         int cnum;
 811 
 812         for ( cnum = 0 ; cnum < gdata->ccount ; cnum++ ) {
 813             ClassInfo *cp;
 814 
 815             cp = gdata->classes + cnum;
 816             (void)free((void*)cp->name);
 817             if ( cp->mcount > 0 ) {
 818                 int mnum;
 819 
 820                 for ( mnum = 0 ; mnum < cp->mcount ; mnum++ ) {
 821                     MethodInfo *mp;
 822 
 823                     mp = cp->methods + mnum;
 824                     (void)free((void*)mp->name);
 825                     (void)free((void*)mp->signature);
 826                 }
 827                 (void)free((void*)cp->methods);
 828             }
 829         }
 830         (void)free((void*)gdata->classes);
 831         gdata->classes = NULL;
 832     }
 833 }