00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "inspectorj/agent/inspectorjagent.h"
00027
00028
00029 using namespace inspectorj::agent;
00030 using inspectorj::client::SessionProfile;
00031 using inspectorj::toolset::ProfileToolSet;
00032
00033
00034
00035
00036 #define MAX_TOKEN_LENGTH 256
00037 #define MAX_THREAD_NAME_LENGTH 512
00038 #define MAX_METHOD_NAME_LENGTH 1024
00039 #define INSPECTORJ_class Mtrace
00040 #define INSPECTORJ_entry method_entry
00041 #define INSPECTORJ_exit method_exit
00042 #define INSPECTORJ_native_entry _method_entry
00043 #define INSPECTORJ_native_exit _method_exit
00044 #define INSPECTORJ_engaged engaged
00045
00046
00047 #define _STRING(s) #s
00048 #define STRING(s) _STRING(s)
00049
00050
00051
00053 typedef struct MethodInfo {
00054 const char *name;
00055 const char *signature;
00056 int calls;
00057 int returns;
00058 } MethodInfo;
00059
00061 typedef struct ClassInfo {
00062 const char *name;
00063 int mcount;
00064 MethodInfo *methods;
00065 int calls;
00066 } ClassInfo;
00067
00068
00073 typedef struct {
00074
00075 JavaVM *vm;
00076 JNIEnv *env;
00077 jvmtiEnv *jvmti;
00078 jboolean vm_is_dead;
00079 jboolean vm_is_started;
00080
00081 jrawMonitorID lock;
00082
00083 SessionProfile *profile;
00084 QList<QRegExp> *regexFilterList;
00085
00086
00087 ClassInfo *classes;
00088 jint ccount;
00089
00090
00091 AgentServer *server;
00092 AgentPacketHandler *cmdHandler;
00093 boost::thread *serverThread;
00094 } AgentGlobalContext;
00095
00096 static AgentGlobalContext *context;
00097
00098
00099
00104 static void
00105 deallocate(jvmtiEnv *jvmti, void *ptr)
00106 {
00107 jvmtiError error;
00108
00109 error = jvmti->Deallocate(static_cast<unsigned char *>(ptr));
00110 check_jvmti_error(jvmti, error, "Cannot deallocate memory");
00111 }
00112
00116 static void *
00117 allocate(jvmtiEnv *jvmti, jint len)
00118 {
00119 jvmtiError error;
00120 void *ptr;
00121
00122 error = jvmti->Allocate(len, (unsigned char **)&ptr);
00123 check_jvmti_error(jvmti, error, "Cannot allocate memory");
00124 return ptr;
00125 }
00126
00130 static void
00131 enter_critical_section(jvmtiEnv *jvmti)
00132 {
00133 jvmtiError error;
00134
00135 error = jvmti->RawMonitorEnter(context->lock);
00136 check_jvmti_error(jvmti, error, "Cannot enter with raw monitor");
00137 }
00138
00142 static void
00143 exit_critical_section(jvmtiEnv *jvmti)
00144 {
00145 jvmtiError error;
00146
00147 error = jvmti->RawMonitorExit(context->lock);
00148 check_jvmti_error(jvmti, error, "Cannot exit with raw monitor");
00149 }
00150
00154 static void
00155 get_thread_name(jvmtiEnv *jvmti, jthread thread, char *tname, int maxlen)
00156 {
00157 jvmtiThreadInfo info;
00158 jvmtiError error;
00159
00160
00161 (void)memset(&info,0, sizeof(info));
00162
00163
00164 (void)strcpy(tname, "Unknown");
00165
00166
00167 error = jvmti->GetThreadInfo(thread, &info);
00168 check_jvmti_error(jvmti, error, "Cannot get thread info");
00169
00170
00171 if ( info.name != NULL ) {
00172 int len;
00173
00174
00175 len = (int)strlen(info.name);
00176 if ( len < maxlen ) {
00177 (void)strcpy(tname, info.name);
00178 }
00179
00180
00181 deallocate(jvmti, (void*)info.name);
00182 }
00183 }
00184
00188 static int
00189 class_compar(const void *e1, const void *e2)
00190 {
00191 ClassInfo *c1 = (ClassInfo*)e1;
00192 ClassInfo *c2 = (ClassInfo*)e2;
00193 if ( c1->calls > c2->calls ) return 1;
00194 if ( c1->calls < c2->calls ) return -1;
00195 return 0;
00196 }
00197
00201 static int
00202 method_compar(const void *e1, const void *e2)
00203 {
00204 MethodInfo *m1 = (MethodInfo*)e1;
00205 MethodInfo *m2 = (MethodInfo*)e2;
00206 if ( m1->calls > m2->calls ) return 1;
00207 if ( m1->calls < m2->calls ) return -1;
00208 return 0;
00209 }
00210
00214 static void
00215 mnum_callbacks(unsigned cnum, const char **names, const char**sigs, int mcount)
00216 {
00217 ClassInfo *cp;
00218 int mnum;
00219
00220 if ( cnum >= (unsigned)context->ccount ) {
00221 AgentLogger::fatal("=> Class number out of range");
00222 }
00223 if ( mcount == 0 ) {
00224 return;
00225 }
00226
00227 cp = context->classes + (int)cnum;
00228 cp->calls = 0;
00229 cp->mcount = mcount;
00230 cp->methods = (MethodInfo*)calloc(mcount, sizeof(MethodInfo));
00231 if ( cp->methods == NULL ) {
00232 AgentLogger::fatal("=> Out of malloc memory");
00233 }
00234
00235 for ( mnum = 0 ; mnum < mcount ; mnum++ ) {
00236 MethodInfo *mp;
00237
00238 mp = cp->methods + mnum;
00239 mp->name = (const char *)strdup(names[mnum]);
00240 if ( mp->name == NULL ) {
00241 AgentLogger::fatal("=> Out of malloc memory");
00242 }
00243 mp->signature = (const char *)strdup(sigs[mnum]);
00244 if ( mp->signature == NULL ) {
00245 AgentLogger::fatal("=> Out of malloc memory");
00246 }
00247 }
00248 }
00249
00253 static void
00254 INSPECTORJ_native_entry(JNIEnv *env, jclass klass, jobject thread, jint cnum, jint mnum)
00255 {
00256 enter_critical_section(context->jvmti); {
00257
00258 if ( !context->vm_is_dead ) {
00259 ClassInfo *cp;
00260 MethodInfo *mp;
00261
00262 if ( cnum >= context->ccount ) {
00263 AgentLogger::fatal("=> Class number out of range");
00264 }
00265 cp = context->classes + cnum;
00266 if ( mnum >= cp->mcount ) {
00267 AgentLogger::fatal("=> Method number out of range");
00268 }
00269 mp = cp->methods + mnum;
00270 if ( interested((char*)cp->name, (char*)mp->name,
00271 context->regexFilterList) ) {
00272 mp->calls++;
00273 cp->calls++;
00274 }
00275 }
00276 } exit_critical_section(context->jvmti);
00277 }
00278
00282 static void
00283 INSPECTORJ_native_exit(JNIEnv *env, jclass klass, jobject thread, jint cnum, jint mnum)
00284 {
00285 enter_critical_section(context->jvmti); {
00286
00287 if ( !context->vm_is_dead ) {
00288 ClassInfo *cp;
00289 MethodInfo *mp;
00290
00291 if ( cnum >= context->ccount ) {
00292 AgentLogger::fatal("=> Class number out of range");
00293 }
00294 cp = context->classes + cnum;
00295 if ( mnum >= cp->mcount ) {
00296 AgentLogger::fatal("=> Method number out of range");
00297 }
00298 mp = cp->methods + mnum;
00299 if ( interested((char*)cp->name, (char*)mp->name,
00300 context->regexFilterList) ) {
00301 mp->returns++;
00302 }
00303 }
00304 } exit_critical_section(context->jvmti);
00305 }
00306
00310 static void JNICALL
00311 cbVMStart(jvmtiEnv *jvmti, JNIEnv *env)
00312 {
00313 enter_critical_section(jvmti); {
00314 jclass klass;
00315 jfieldID field;
00316 int rc;
00317
00318
00319 static JNINativeMethod registry[2] = {
00320 {STRING(INSPECTORJ_native_entry), "(Ljava/lang/Object;II)V",
00321 (void*)&INSPECTORJ_native_entry},
00322 {STRING(INSPECTORJ_native_exit), "(Ljava/lang/Object;II)V",
00323 (void*)&INSPECTORJ_native_exit}
00324 };
00325
00326
00327 AgentLogger::debug("VMStart");
00328
00329
00330 klass = env->FindClass(STRING(INSPECTORJ_class));
00331 if ( klass == NULL ) {
00332 AgentLogger::fatal("=> JNI: Cannot find %s with FindClass",
00333 STRING(INSPECTORJ_class));
00334 }
00335 rc = env->RegisterNatives(klass, registry, 2);
00336 if ( rc != 0 ) {
00337 AgentLogger::fatal("=> JNI: Cannot register native methods for %s",
00338 STRING(INSPECTORJ_class));
00339 }
00340
00341
00342 field = env->GetStaticFieldID(klass, STRING(INSPECTORJ_engaged), "I");
00343 if ( field == NULL ) {
00344 AgentLogger::fatal("=> JNI: Cannot get field from %s",
00345 STRING(INSPECTORJ_class));
00346 }
00347 env->SetStaticIntField(klass, field, 1);
00348
00349
00350 context->vm_is_started = JNI_TRUE;
00351
00352 } exit_critical_section(jvmti);
00353 }
00354
00355
00359 void startServer()
00360 {
00361 AgentLogger::print("*****************************\n");
00362 AgentLogger::print(" inspectorj server starting\n");
00363 AgentLogger::print(" listening on port %s\n",
00364 context->profile->getConnection().port.toLocal8Bit().data());
00365 AgentLogger::print("*****************************\n");
00366 context->server->start();
00367 }
00368
00372 static void JNICALL
00373 cbVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
00374 {
00375 enter_critical_section(jvmti); {
00376 char tname[MAX_THREAD_NAME_LENGTH];
00377 static jvmtiEvent events[] =
00378 { JVMTI_EVENT_THREAD_START, JVMTI_EVENT_THREAD_END };
00379 int i;
00380
00381
00382 get_thread_name(jvmti, thread, tname, sizeof(tname));
00383 AgentLogger::debug("VMInit %s", tname);
00384
00385
00386
00387
00388
00389 for( i=0; i < (int)(sizeof(events)/sizeof(jvmtiEvent)); i++) {
00390 jvmtiError error;
00391
00392
00393 error = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
00394 events[i], (jthread)NULL);
00395 check_jvmti_error(jvmti, error, "Cannot set event notification");
00396 }
00397
00398 } exit_critical_section(jvmti);
00399
00400 context->env = env;
00401
00402
00403 AgentPacketHandler *cmdHandler = new AgentPacketHandler(context->vm, context->env, context->jvmti);
00404 AgentServer *server = new AgentServer(
00405 context->profile->getConnection().port.toInt(),
00406 cmdHandler);
00407
00408 context->server = server;
00409 context->cmdHandler = cmdHandler;
00410
00411 context->serverThread = &boost::thread(startServer);
00412 }
00413
00417 static void JNICALL
00418 cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env)
00419 {
00420 enter_critical_section(jvmti); {
00421 jclass klass;
00422 jfieldID field;
00423
00424
00425 AgentLogger::info("VMDeath");
00426
00427
00428 klass = env->FindClass(STRING(INSPECTORJ_class));
00429 if ( klass == NULL ) {
00430 AgentLogger::fatal("=> JNI: Cannot find %s with FindClass",
00431 STRING(INSPECTORJ_class));
00432 }
00433 field = env->GetStaticFieldID(klass, STRING(INSPECTORJ_engaged), "I");
00434 if ( field == NULL ) {
00435 AgentLogger::fatal("=> JNI: Cannot get field from %s",
00436 STRING(INSPECTORJ_class));
00437 }
00438 env->SetStaticIntField(klass, field, 0);
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 context->vm_is_dead = JNI_TRUE;
00452
00453
00454 AgentLogger::info("Begin Class Stats");
00455 if ( context->ccount > 0 ) {
00456 int cnum;
00457
00458
00459
00460 qsort(context->classes, context->ccount, sizeof(ClassInfo),
00461 &class_compar);
00462
00463
00464 for ( cnum=context->ccount-1 ;
00465 cnum >= 0 && cnum >= context->ccount - 4;
00466 cnum-- ) {
00467 ClassInfo *cp;
00468 int mnum;
00469
00470 cp = context->classes + cnum;
00471 AgentLogger::info("Class %s %d calls", cp->name, cp->calls);
00472 if ( cp->calls==0 ) continue;
00473
00474
00475
00476 qsort(cp->methods, cp->mcount, sizeof(MethodInfo),
00477 &method_compar);
00478 for ( mnum=cp->mcount-1 ; mnum >= 0 ; mnum-- ) {
00479 MethodInfo *mp;
00480
00481 mp = cp->methods + mnum;
00482 if ( mp->calls==0 ) continue;
00483 AgentLogger::info("\tMethod %s %s %d calls %d returns",
00484 mp->name, mp->signature, mp->calls, mp->returns);
00485 }
00486 }
00487 }
00488 AgentLogger::info("End Class Stats");
00489 (void)fflush(stdout);
00490
00491 } exit_critical_section(jvmti);
00492
00493 }
00494
00498 static void JNICALL
00499 cbThreadStart(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
00500 {
00501 enter_critical_section(jvmti); {
00502
00503 if ( !context->vm_is_dead ) {
00504 char tname[MAX_THREAD_NAME_LENGTH];
00505
00506 get_thread_name(jvmti, thread, tname, sizeof(tname));
00507 AgentLogger::info("ThreadStart %s", tname);
00508 }
00509 } exit_critical_section(jvmti);
00510 }
00511
00515 static void JNICALL
00516 cbThreadEnd(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
00517 {
00518 enter_critical_section(jvmti); {
00519
00520 if ( !context->vm_is_dead ) {
00521 char tname[MAX_THREAD_NAME_LENGTH];
00522
00523 get_thread_name(jvmti, thread, tname, sizeof(tname));
00524 AgentLogger::info("ThreadEnd %s", tname);
00525 }
00526 } exit_critical_section(jvmti);
00527 }
00528
00532 static void JNICALL
00533 cbClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv* env,
00534 jclass class_being_redefined, jobject loader,
00535 const char* name, jobject protection_domain,
00536 jint class_data_len, const unsigned char* class_data,
00537 jint* new_class_data_len, unsigned char** new_class_data)
00538 {
00539 enter_critical_section(jvmti); {
00540
00541 if ( !context->vm_is_dead ) {
00542
00543 const char *classname;
00544
00545
00546 if ( name == NULL ) {
00547 classname = java_crw_demo_classname(class_data, class_data_len,
00548 NULL);
00549 if ( classname == NULL ) {
00550 AgentLogger::fatal("=> No classname inside classfile");
00551 }
00552 } else {
00553 classname = strdup(name);
00554 if ( classname == NULL ) {
00555 AgentLogger::fatal("=> Out of malloc memory");
00556 }
00557 }
00558
00559 *new_class_data_len = 0;
00560 *new_class_data = NULL;
00561
00562
00563 if ( interested((char*)classname, "", context->regexFilterList)
00564 && strcmp(classname, STRING(INSPECTORJ_class)) != 0 ) {
00565 jint cnum;
00566 int system_class;
00567 unsigned char *new_image;
00568 long new_length;
00569 ClassInfo *cp;
00570
00571
00572 cnum = context->ccount++;
00573
00574
00575 if ( context->classes == NULL ) {
00576 context->classes = (ClassInfo*)malloc(
00577 context->ccount*sizeof(ClassInfo));
00578 } else {
00579 context->classes = (ClassInfo*)
00580 realloc((void*)context->classes,
00581 context->ccount*sizeof(ClassInfo));
00582 }
00583 if ( context->classes == NULL ) {
00584 AgentLogger::fatal("=> Out of malloc memory");
00585 }
00586 cp = context->classes + cnum;
00587 cp->name = (const char *)strdup(classname);
00588 if ( cp->name == NULL ) {
00589 AgentLogger::fatal("=> Out of malloc memory");
00590 }
00591 cp->calls = 0;
00592 cp->mcount = 0;
00593 cp->methods = NULL;
00594
00595
00596
00597
00598
00599 system_class = 0;
00600 if ( !context->vm_is_started ) {
00601 system_class = 1;
00602 }
00603
00604 new_image = NULL;
00605 new_length = 0;
00606
00607
00608 java_crw_demo(cnum,
00609 classname,
00610 class_data,
00611 class_data_len,
00612 system_class,
00613 STRING(INSPECTORJ_class), "L" STRING(INSPECTORJ_class) ";",
00614 STRING(INSPECTORJ_entry), "(II)V",
00615 STRING(INSPECTORJ_exit), "(II)V",
00616 NULL, NULL,
00617 NULL, NULL,
00618 &new_image,
00619 &new_length,
00620 NULL,
00621 &mnum_callbacks);
00622
00623
00624
00625
00626 if ( new_length > 0 ) {
00627 unsigned char *jvmti_space;
00628
00629 jvmti_space = (unsigned char *)allocate(jvmti, (jint)new_length);
00630 (void)memcpy((void*)jvmti_space, (void*)new_image, (int)new_length);
00631 *new_class_data_len = (jint)new_length;
00632 *new_class_data = jvmti_space;
00633 }
00634
00635
00636 if ( new_image != NULL ) {
00637 (void)free((void*)new_image);
00638 }
00639 }
00640 (void)free((void*)classname);
00641 }
00642 } exit_critical_section(jvmti);
00643 }
00644
00648 static void parseOptions(char *options)
00649 {
00650 char token[MAX_TOKEN_LENGTH];
00651 char *next;
00652
00653
00654 if ( options == NULL ) {
00655 options = "help";
00656 }
00657
00658
00659 next = getToken(options, ",=", token, sizeof(token));
00660
00661
00662 while ( next != NULL ) {
00663 if ( strcmp(token,"help")==0 ) {
00664 AgentLogger::println("");
00665 AgentLogger::println("====================");
00666 AgentLogger::println("inspectorJ JVM Agent");
00667 AgentLogger::println("====================");
00668 AgentLogger::println("");
00669 AgentLogger::println(" java -agent:ij_agent=profile=<path_to_profile>[,=options,...]");
00670 AgentLogger::println("");
00671 AgentLogger::println("\t port=xxxx\txxxx is the port number used by the agent server");
00672 AgentLogger::println("");
00673 AgentLogger::println(" The options are comma separated:");
00674 AgentLogger::println("\t help\t\tPrint help information");
00675 AgentLogger::println("\t loglevel=n\tlogging [0 = error, 1 = warn, (2) = info]");
00676 AgentLogger::println("");
00677 exit(0);
00678 } else if ( strcmp(token,"loglevel")==0 ) {
00679 char number[MAX_TOKEN_LENGTH];
00680
00681
00682 next = getToken(next, ",=", number, (int)sizeof(number));
00683
00684 if ( next==NULL ) {
00685 AgentLogger::error("=> loglevel=n option error");
00686 next = "1";
00687 }
00688
00689 AgentLogger::loglevel = atoi(number);
00690 } else if ( strcmp(token,"profile")==0 ) {
00691 char fileName[MAX_TOKEN_LENGTH];
00692
00693
00694 next = getToken(next, ",=", fileName, (int)sizeof(fileName));
00695
00696
00697 if ( next==NULL ) {
00698 AgentLogger::fatal("=> profile option error");
00699 }
00700
00701 context->profile = new SessionProfile();
00702 if (!ProfileToolSet::loadProfile(*(context->profile), fileName)) {
00703 AgentLogger::fatal("=> Could not load profile: %s", fileName);
00704 }
00705 context->regexFilterList = new QList<QRegExp>();
00706
00707
00708 if (context->profile) {
00709 QStringList filters = context->profile->getClassFilters();
00710 QStringListIterator filterIter(filters);
00711 while(filterIter.hasNext()) {
00712 QRegExp regexp;
00713 createAgentClassFilter(regexp, filterIter.next());
00714 *(context->regexFilterList) << regexp;
00715 }
00716 }
00717 } else if ( token[0]!=0 ) {
00718
00719 AgentLogger::fatal("=> Unknown option: %s", token);
00720 }
00721
00722 next = getToken(next, ",=", token, sizeof(token));
00723 }
00724 }
00725
00730 JNIEXPORT jint JNICALL
00731 Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
00732 {
00733 static AgentGlobalContext ctx;
00734 jvmtiEnv *jvmti;
00735 jvmtiError error;
00736 jint res;
00737 jvmtiCapabilities capabilities;
00738 jvmtiEventCallbacks callbacks;
00739
00740
00741
00742
00743
00744
00745
00746 (void)memset((void*)&ctx, 0, sizeof(ctx));
00747 context = &ctx;
00748
00749
00750 res = vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1);
00751 if (res != JNI_OK) {
00752
00753
00754
00755 AgentLogger::fatal("=> Unable to access JVMTI Version 1 (0x%x),"
00756 " is your J2SE a 1.5 or newer version?"
00757 " JNIEnv's GetEnv() returned %d",
00758 JVMTI_VERSION_1, res);
00759 }
00760
00761 context->vm = vm;
00762
00763
00764 context->jvmti = jvmti;
00765
00766
00767 parseOptions(options);
00768
00769
00770
00771
00772
00773 (void)memset(&capabilities,0, sizeof(capabilities));
00774 capabilities.can_generate_all_class_hook_events = 1;
00775 capabilities.can_get_source_file_name = 1;
00776 capabilities.can_access_local_variables = 1;
00777 capabilities.can_get_line_numbers = 1;
00778 error = jvmti->AddCapabilities(&capabilities);
00779 check_jvmti_error(jvmti, error, "Unable to get necessary JVMTI capabilities.");
00780
00781
00782
00783
00784 (void)memset(&callbacks,0, sizeof(callbacks));
00785
00786 callbacks.VMStart = &cbVMStart;
00787
00788 callbacks.VMInit = &cbVMInit;
00789
00790 callbacks.VMDeath = &cbVMDeath;
00791
00792 callbacks.ClassFileLoadHook = &cbClassFileLoadHook;
00793
00794 callbacks.ThreadStart = &cbThreadStart;
00795
00796 callbacks.ThreadEnd = &cbThreadEnd;
00797 error = jvmti->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks));
00798 check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks");
00799
00800
00801
00802
00803
00804 error = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
00805 JVMTI_EVENT_VM_START, (jthread)NULL);
00806 check_jvmti_error(jvmti, error, "Cannot set event notification");
00807 error = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
00808 JVMTI_EVENT_VM_INIT, (jthread)NULL);
00809 check_jvmti_error(jvmti, error, "Cannot set event notification");
00810 error = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
00811 JVMTI_EVENT_VM_DEATH, (jthread)NULL);
00812 check_jvmti_error(jvmti, error, "Cannot set event notification");
00813 error = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
00814 JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, (jthread)NULL);
00815 check_jvmti_error(jvmti, error, "Cannot set event notification");
00816
00817
00818
00819
00820 error = jvmti->CreateRawMonitor("inspectorj agent", &(context->lock));
00821 check_jvmti_error(jvmti, error, "Cannot create raw monitor");
00822
00823
00824 return JNI_OK;
00825 }
00826
00831 JNIEXPORT void JNICALL
00832 Agent_OnUnload(JavaVM *vm)
00833 {
00834
00835
00836
00837 if ( context->server != NULL ) {
00838 AgentLogger::print("**********************************\n");
00839 AgentLogger::print(" shutting down inspectorj server\n");
00840
00841
00842 context->server->stop();
00843
00844
00845 while(context->server->isStarted()) { }
00846 AgentLogger::print(" unloading inspectorj agent\n");
00847
00848 delete context->server;
00849 context->server = NULL;
00850 }
00851
00852
00853 if ( context->cmdHandler != NULL ) {
00854 delete context->cmdHandler;
00855 context->cmdHandler = NULL;
00856 }
00857
00858
00859 if ( context->regexFilterList != NULL ) {
00860 delete context->regexFilterList;
00861 context->regexFilterList = NULL;
00862 }
00863
00864
00865 if ( context->profile != NULL ) {
00866 delete context->profile;
00867 context->profile = NULL;
00868 }
00869
00870 if ( context->classes != NULL ) {
00871 int cnum;
00872
00873 for ( cnum = 0 ; cnum < context->ccount ; cnum++ ) {
00874 ClassInfo *cp;
00875 cp = context->classes + cnum;
00876 (void)free((void*)cp->name);
00877
00878 if ( cp->mcount > 0 ) {
00879 int mnum;
00880 for ( mnum = 0 ; mnum < cp->mcount ; mnum++ ) {
00881 MethodInfo *mp;
00882 mp = cp->methods + mnum;
00883 (void)free((void*)mp->name);
00884 (void)free((void*)mp->signature);
00885 }
00886 (void)free((void*)cp->methods);
00887 }
00888 }
00889
00890 (void)free((void*)context->classes);
00891 context->classes = NULL;
00892 }
00893 AgentLogger::print("**********************************\n");
00894 }
00895