/* 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"); } }
int print_method_info(void * const value, void * const f_arg) { (void) f_arg; const jmethodID method_id = ((method_stat_t *)value)->id; const unsigned long counter = ((method_stat_t *)value)->counter; jvmtiError error; char *name; char *sig; char *ptr; error = (*jvmti)->GetMethodName(jvmti, method_id, &name, &sig, &ptr); check_jvmti_error(jvmti, error, "Cannot get method name"); jclass decl_class; error = (*jvmti)->GetMethodDeclaringClass(jvmti, method_id, &decl_class); check_jvmti_error(jvmti, error, "Cannot get declaring class"); char *class_sig; char *class_status; error = (*jvmti)->GetClassSignature(jvmti, decl_class, &class_sig, &class_status); check_jvmti_error(jvmti, error, "Cannot get class signature"); printf("%ld\tclass %s -> %s(%s)\n", counter, class_sig, name, sig); jvmti_dealloc((unsigned char *) name); jvmti_dealloc((unsigned char *) sig); jvmti_dealloc((unsigned char *) ptr); jvmti_dealloc((unsigned char *) class_sig); jvmti_dealloc((unsigned char *) class_status); return MAP_OK; }
/* Given a jvmtiEnv* and jobject, find the Monitor instance or create one */ Monitor * Agent::get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object) { jvmtiError err; Monitor *m; jlong tag; m = NULL; tag = (jlong)0; err = jvmti->GetTag(object, &tag); check_jvmti_error(jvmti, err, "get tag"); /*LINTED*/ m = (Monitor *)(void *)(ptrdiff_t)tag; if ( m == NULL ) { m = new Monitor(jvmti, env, object); /* Save monitor on list */ if (monitor_count == monitor_list_size) { monitor_list_size += monitor_list_grow_size; monitor_list = (Monitor**)realloc((void*)monitor_list, (monitor_list_size)*(int)sizeof(Monitor*)); } monitor_list[monitor_count] = m; m->set_slot(monitor_count); monitor_count++; /*LINTED*/ tag = (jlong)(ptrdiff_t)(void *)m; err = jvmti->SetTag(object, tag); check_jvmti_error(jvmti, err, "set tag"); } return m; }
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jint rc; jvmtiError err; jvmtiEventCallbacks callbacks; jvmtiEnv *jvmti; /* Get JVMTI environment */ rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION); if (rc != JNI_OK) { fatal_error("ERROR: Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc); return -1; } /* Set callbacks and enable event notifications */ memset(&callbacks, 0, sizeof(callbacks)); callbacks.VMInit = &vm_init; err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks)); check_jvmti_error(jvmti, err, "set event callbacks"); err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); check_jvmti_error(jvmti, err, "set event notify"); return 0; }
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { jvmtiEventCallbacks *evCbs; jvmtiCapabilities caps; jvmtiEnv *jvmti; jint rc; jint jvmtiVer; agent_options = options ? strdup(options) : ""; evCbs = get_jvmti_callbacks(); memset(evCbs, 0, sizeof(*evCbs)); memset(&caps, 0, sizeof(caps)); evCbs->VMInit = cbVMInit; evCbs->VMDeath = cbVMDeath; caps.can_generate_breakpoint_events = 1; caps.can_generate_method_entry_events = 1; caps.can_generate_method_exit_events = 1; caps.can_generate_exception_events = 1; caps.can_tag_objects = 1; caps.can_get_source_file_name = 1; caps.can_get_line_numbers = 1; caps.can_access_local_variables = 1; caps.can_generate_single_step_events = 1; /* Used for line-oriented stepping */ /* caps.can_generate_frame_pop_events = 1; */ caps.can_force_early_return = 1; rc = (*jvm)->GetEnv(jvm, (void **)&jvmti, JVMTI_VERSION_1_0); if(rc < 0) { fprintf(stderr, "Failed to get JVMTI env\n"); return JNI_ERR; } Gagent.jvm = jvm; Gagent.jvmti = jvmti; Gagent.jerr = (*Gagent.jvmti)->GetVersionNumber(Gagent.jvmti, &jvmtiVer); check_jvmti_error(Gagent.jvmti, Gagent.jerr); printf("JVMTI version %d.%d.%d\n", (jvmtiVer & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR, (jvmtiVer & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR, (jvmtiVer & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO); Gagent.jerr = (*Gagent.jvmti)->AddCapabilities(Gagent.jvmti, &caps); check_jvmti_error(Gagent.jvmti, Gagent.jerr); Gagent.jerr = (*Gagent.jvmti)->SetEventCallbacks(Gagent.jvmti, evCbs, sizeof(jvmtiEventCallbacks)); check_jvmti_error(Gagent.jvmti, Gagent.jerr); /* Check that any calls to SetEventNotificationMode are valid in the OnLoad phase before calling here. */ Gagent.jerr = event_change(Gagent.jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); check_jvmti_error(Gagent.jvmti, Gagent.jerr); Gagent.jerr = event_change(Gagent.jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL); check_jvmti_error(Gagent.jvmti, Gagent.jerr); return JNI_OK; }
/* Add demo jar file to boot class path (the BCI Tracker class must be * in the boot classpath) * * WARNING: This code assumes that the jar file can be found at one of: * ${JAVA_HOME}/demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar * ${JAVA_HOME}/../demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar * where JAVA_HOME may refer to the jre directory. * Both these values are added to the boot classpath. * These locations are only true for these demos, installed * in the JDK area. Platform specific code could be used to * find the location of the DLL or .so library, and construct a * path name to the jar file, relative to the library location. */ void add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name) { jvmtiError error; char *file_sep; int max_len; char *java_home; char jar_path[FILENAME_MAX+1]; java_home = NULL; error = (*jvmti)->GetSystemProperty(jvmti, "java.home", &java_home); check_jvmti_error(jvmti, error, "Cannot get java.home property value"); if ( java_home == NULL || java_home[0] == 0 ) { fatal_error("ERROR: Java home not found\n"); } #ifdef WIN32 file_sep = "\\"; #else file_sep = "/"; #endif max_len = (int)(strlen(java_home) + strlen(demo_name)*2 + strlen(file_sep)*5 + 16 /* ".." "demo" "jvmti" ".jar" NULL */ ); if ( max_len > (int)sizeof(jar_path) ) { fatal_error("ERROR: Path to jar file too long\n"); } (void)strcpy(jar_path, java_home); (void)strcat(jar_path, file_sep); (void)strcat(jar_path, "demo"); (void)strcat(jar_path, file_sep); (void)strcat(jar_path, "jvmti"); (void)strcat(jar_path, file_sep); (void)strcat(jar_path, demo_name); (void)strcat(jar_path, file_sep); (void)strcat(jar_path, demo_name); (void)strcat(jar_path, ".jar"); error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path); check_jvmti_error(jvmti, error, "Cannot add to boot classpath"); (void)strcpy(jar_path, java_home); (void)strcat(jar_path, file_sep); (void)strcat(jar_path, ".."); (void)strcat(jar_path, file_sep); (void)strcat(jar_path, "demo"); (void)strcat(jar_path, file_sep); (void)strcat(jar_path, "jvmti"); (void)strcat(jar_path, file_sep); (void)strcat(jar_path, demo_name); (void)strcat(jar_path, file_sep); (void)strcat(jar_path, demo_name); (void)strcat(jar_path, ".jar"); error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path); check_jvmti_error(jvmti, error, "Cannot add to boot classpath"); }
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved){ PORT_ACCESS_FROM_JAVAVM(vm); VMI_ACCESS_FROM_JAVAVM(vm); jvmtiError jvmti_err; JNIEnv *env = NULL; static jvmtiEnv *jvmti; jvmtiCapabilities updatecapabilities; jint err = (*vm)->GetEnv(vm, (void **)&jnienv, JNI_VERSION_1_2); if(JNI_OK != err){ return err; } if(!gdata){ jvmtiCapabilities capabilities; jvmtiError jvmti_err; jvmtiEventCallbacks callbacks; gdata = hymem_allocate_memory(sizeof(AgentData)); //get jvmti environment err = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_1_0); if(JNI_OK != err){ return err; } gdata->jvmti = jvmti; //get JVMTI potential capabilities jvmti_err = (*jvmti)->GetPotentialCapabilities(jvmti, &capabilities); check_jvmti_error(env, jvmti_err, "Cannot get JVMTI potential capabilities."); gsupport_redefine = (capabilities.can_redefine_classes == 1); //set events callback function (void)memset(&callbacks, 0, sizeof(callbacks)); callbacks.ClassFileLoadHook = &callbackClassFileLoadHook; callbacks.VMInit = &callbackVMInit; jvmti_err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(jvmtiEventCallbacks)); check_jvmti_error(env, jvmti_err, "Cannot set JVMTI event callback functions."); //enable classfileloadhook event jvmti_err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); check_jvmti_error(env, jvmti_err, "Cannot set JVMTI VMInit event notification mode."); } err = Parse_Options(vm,jnienv, gdata->jvmti,options); //update capabilities JVMTI memset(&updatecapabilities, 0, sizeof(updatecapabilities)); updatecapabilities.can_generate_all_class_hook_events = 1; updatecapabilities.can_redefine_classes = gsupport_redefine; //FIXME VM doesnot support the capbility right now. //capabilities.can_redefine_any_class = 1; jvmti_err = (*jvmti)->AddCapabilities(jvmti, &updatecapabilities); check_jvmti_error(env, jvmti_err, "Cannot add JVMTI capabilities."); return err; }
/* * Callback to notify us when a GC finishes. When a GC finishes, * we wake up our GC thread and free all tags that need to be freed. */ static void JNICALL gc_finish(jvmtiEnv* jvmti_env) { jvmtiError err; err = gdata->jvmti->RawMonitorEnter(gcLock); check_jvmti_error(gdata->jvmti, err, "raw monitor enter"); gc_count++; err = gdata->jvmti->RawMonitorNotify(gcLock); check_jvmti_error(gdata->jvmti, err, "raw monitor notify"); err = gdata->jvmti->RawMonitorExit(gcLock); check_jvmti_error(gdata->jvmti, err, "raw monitor exit"); }
/* 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"); }
// Exit a critical section by doing a JVMTI Raw Monitor Exit static void exit_critical_section(jvmtiEnv *jvmti) { jvmtiError error; error = (*jvmti)->RawMonitorExit(jvmti, gdata->lock); // error = (*jvmti).RawMonitorExit( gdata->lock); check_jvmti_error(jvmti, error, "Cannot exit with raw monitor"); }
void tl_init(jvmtiEnv * env) { jvmti_env = env; jvmtiError error = (*jvmti_env)->CreateRawMonitor(jvmti_env, "thread id", &threadID_lock); check_jvmti_error(jvmti_env, error, "Cannot create raw monitor"); }
/* All memory allocated by JVMTI must be freed by the JVMTI Deallocate * interface. */ void deallocate(jvmtiEnv *jvmti, void *ptr) { jvmtiError error; #ifdef DEBUG size_t *p = (size_t *) ptr; char *start = (char *) ptr; size_t len = p[-2]; char *end = &start[len]; size_t start_guard = p[-1]; size_t end_guard = ((size_t *)end)[0]; if (start_guard != 0xdfdfdfdfdfdfdfdf) { fatal_error("start guard got stomped"); } if (end_guard != 0xdfdfdfdfdfdfdfdf) { fatal_error("end guard got stomped"); } ptr = &(p[-2]); #endif error = (*jvmti)->Deallocate(jvmti, ptr); check_jvmti_error(jvmti, error, "Cannot deallocate memory"); }
/* Allocation of JVMTI managed memory */ void * allocate(jvmtiEnv *jvmti, size_t len) { jvmtiError error; void *ptr = NULL; #ifdef DEBUG size_t *p = NULL; size_t l = len; len += 3 * sizeof(size_t); #endif error = (*jvmti)->Allocate(jvmti, (jlong) len, (unsigned char **)&ptr); check_jvmti_error(jvmti, error, "Cannot allocate memory"); #ifdef DEBUG memset(ptr, 0xdf, len); p = (size_t *) ptr; p[0] = l; ptr = &(p[2]); #endif return ptr; }
void deallocate(jvmtiEnv *jvmti, void *ptr) { jvmtiError error; error = (*jvmti)->Deallocate(jvmti, ptr); check_jvmti_error(jvmti, error, "Cannot deallocate memory"); }
// VM Death callback static void JNICALL callbackVMDeath(jvmtiEnv *jvmti_env, JNIEnv* jni_env) { jvmtiError err; /// Make sure everything has been garbage collected err = jvmti->ForceGarbageCollection(); check_jvmti_error(jvmti, err, "Forced garbage collection failed"); enter_critical_section(jvmti); { err = jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_DATA_DUMP_REQUEST, NULL); check_jvmti_error(jvmti, err, "SetEventNotificationMode failure"); } exit_critical_section(jvmti); }
/* * Implementation of _setTag JNI function. */ JNIEXPORT static void JNICALL setObjExpression(JNIEnv *env, jclass klass, jobject o, jobject expr) { if (gdata->vmDead) { return; } if(!o) { return; } jvmtiError error; jlong tag; if (expr) { //First see if there's already something set here error =gdata->jvmti->GetTag(o,&tag); if(tag) { //Delete reference to old thing env->DeleteGlobalRef((jobject)(ptrdiff_t) tag); } //Set the tag, make a new global reference to it error = gdata->jvmti->SetTag(o, (jlong) (ptrdiff_t) (void*) env->NewGlobalRef(expr)); } else { error = gdata->jvmti->SetTag(o, 0); } if(error == JVMTI_ERROR_WRONG_PHASE) return; check_jvmti_error(gdata->jvmti, error, "Cannot set object tag"); }
/* 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); }
/* Get a name for a jthread */ static void get_thread_name(jvmtiEnv *jvmti, jthread thread, char *tname, int maxlen) { jvmtiThreadInfo info; jvmtiError error; /* Make sure the stack variables are garbage free */ (void)memset(&info,0, sizeof(info)); /* Assume the name is unknown for now */ (void)strcpy(tname, "Unknown"); /* Get the thread information, which includes the name */ error = (*jvmti)->GetThreadInfo(jvmti, thread, &info); check_jvmti_error(jvmti, error, "Cannot get thread info"); /* The thread might not have a name, be careful here. */ if ( info.name != NULL ) { int len; /* Copy the thread name into tname if it will fit */ len = (int)strlen(info.name); if ( len < maxlen ) { (void)strcpy(tname, info.name); } /* Every string allocated by JVMTI needs to be freed */ deallocate(jvmti, (void*)info.name); } }
/* * Callback we get when the JVM is initialized. We use this time to setup our GC thread */ static void JNICALL callbackVMInit(jvmtiEnv * jvmti, JNIEnv * env, jthread thread) { jvmtiError err; err = jvmti->RunAgentThread(alloc_thread(env), &gcWorker, NULL, JVMTI_THREAD_MAX_PRIORITY); check_jvmti_error(jvmti, err, "Unable to run agent cleanup thread"); }
/* * Since we create a global reference to whatever we tag an object with, we need to clean this up * when the tagged object is garbage collected - otherwise tags wouldn't ever be garbage collected. * When a tagged object is GC'ed, we add its tag to a deletion queue. We will process the queue at the next GC. */ static void JNICALL cbObjectFree(jvmtiEnv *jvmti_env, jlong tag) { if (gdata->vmDead) { return; } jvmtiError error; if (tag) { error = gdata->jvmti->RawMonitorEnter(deleteQueueLock); check_jvmti_error(jvmti_env, error, "raw monitor enter"); DeleteQueue* tmp = deleteQueue; deleteQueue = new DeleteQueue(); deleteQueue->next = tmp; deleteQueue->obj = (jobject) (ptrdiff_t) tag; error = gdata->jvmti->RawMonitorExit(deleteQueueLock); check_jvmti_error(jvmti_env, error, "raw monitor exit"); } }
/* Enter raw monitor */ static void menter(jvmtiEnv *jvmti, jrawMonitorID rmon) { jvmtiError err; err = jvmti->RawMonitorEnter(rmon); check_jvmti_error(jvmti, err, "raw monitor enter"); }
/* Enter a critical section by doing a JVMTI Raw Monitor Enter */ static void enter_critical_section(jvmtiEnv *jvmti) { jvmtiError error; error = (*jvmti)->RawMonitorEnter(jvmti, gdata->lock); check_jvmti_error(jvmti, error, "Cannot enter with raw monitor"); }
/* Exit raw monitor */ static void mexit(jvmtiEnv *jvmti, jrawMonitorID rmon) { jvmtiError err; err = jvmti->RawMonitorExit(rmon); check_jvmti_error(jvmti, err, "raw monitor exit"); }
/* Exit agent monitor protected section */ static void exitAgentMonitor(jvmtiEnv *jvmti) { jvmtiError err; err = (*jvmti)->RawMonitorExit(jvmti, gdata->lock); check_jvmti_error(jvmti, err, "raw monitor exit"); }
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jint rc; jvmtiError err; jvmtiCapabilities capabilities; jvmtiEventCallbacks callbacks; jvmtiEnv *jvmti; /* Get JVMTI environment */ jvmti = NULL; rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION); if (rc != JNI_OK) { fatal_error("ERROR: Unable to create jvmtiEnv, error=%d\n", rc); return -1; } if ( jvmti == NULL ) { fatal_error("ERROR: No jvmtiEnv* returned from GetEnv\n"); } /* Get/Add JVMTI capabilities */ (void)memset(&capabilities, 0, sizeof(capabilities)); capabilities.can_tag_objects = 1; capabilities.can_generate_garbage_collection_events = 1; err = (*jvmti)->AddCapabilities(jvmti, &capabilities); check_jvmti_error(jvmti, err, "add capabilities"); /* Create the raw monitor */ err = (*jvmti)->CreateRawMonitor(jvmti, "agent lock", &(gdata->lock)); check_jvmti_error(jvmti, err, "create raw monitor"); /* Set callbacks and enable event notifications */ memset(&callbacks, 0, sizeof(callbacks)); callbacks.VMInit = &vmInit; callbacks.VMDeath = &vmDeath; callbacks.DataDumpRequest = &dataDumpRequest; err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks)); check_jvmti_error(jvmti, err, "set event callbacks"); err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); check_jvmti_error(jvmti, err, "set event notifications"); err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL); check_jvmti_error(jvmti, err, "set event notifications"); return 0; }
// Enter a critical section by doing a JVMTI Raw Monitor Enter static void enter_critical_section(jvmtiEnv *jvmti) { jvmtiError error; error = (*jvmti)->RawMonitorEnter(jvmti, gdata->lock); //the error function does not take 2 arguments // error = (*jvmti).RawMonitorEnter(gdata->lock); check_jvmti_error(jvmti, error, "Cannot enter with raw monitor"); }
/* Agent_OnLoad() is called first, we prepare for a COMPILED_METHOD_LOAD * event here. */ JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jint rc; jvmtiError err; jvmtiCapabilities capabilities; jvmtiEventCallbacks callbacks; fp = fopen(OUTPUT_FILE, "w"); if (fp == NULL) { fatal_error("ERROR: %s: Unable to create output file\n", OUTPUT_FILE); return -1; } /* Get JVMTI environment */ rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION); if (rc != JNI_OK) { fatal_error( "ERROR: Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc); return -1; } /* add JVMTI capabilities */ memset(&capabilities,0, sizeof(capabilities)); capabilities.can_generate_compiled_method_load_events = 1; err = (*jvmti)->AddCapabilities(jvmti, &capabilities); check_jvmti_error(jvmti, err, "add capabilities"); /* set JVMTI callbacks for events */ memset(&callbacks, 0, sizeof(callbacks)); callbacks.CompiledMethodLoad = &compiled_method_load; err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks)); check_jvmti_error(jvmti, err, "set event callbacks"); /* enable JVMTI events */ err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL); check_jvmti_error(jvmti, err, "set event notify"); /* create coordination monitor */ err = (*jvmti)->CreateRawMonitor(jvmti, "agent lock", &lock); check_jvmti_error(jvmti, err, "create raw monitor"); return 0; }
void* allocate(jvmtiEnv *jvmti, jint len) { jvmtiError error; void *ptr; error = (*jvmti)->Allocate(jvmti, len, (unsigned char **)&ptr); check_jvmti_error(jvmti, error, "Cannot allocate memory"); return ptr; }
static char * __thread_name (jvmtiEnv * jvmti) { assert (jvmti != NULL && jvm_is_initialized); jvmtiThreadInfo info; jvmtiError error = (* jvmti)->GetThreadInfo (jvmti, NULL, &info); check_jvmti_error (jvmti, error, "failed to get current thread info"); return info.name; }
/* 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; }