-
-
Save nidefawl/fe7a718e5950b069172d to your computer and use it in GitHub Desktop.
JNI agent example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) | |
{ | |
jvmtiError error; | |
jint res; | |
jvmtiEnv *jvmti = NULL; | |
/* Setup initial global agent data area | |
* Use of static/extern data should be handled carefully here. | |
* We need to make sure that we are able to cleanup after ourselves | |
* so anything allocated in this library needs to be freed in | |
* the Agent_OnUnload() function. | |
*/ | |
/* We need to first get the jvmtiEnv* or JVMTI environment */ | |
res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_0); | |
if (res != JNI_OK || jvmti == NULL) | |
{ | |
/* This means that the VM was unable to obtain this version of the | |
* JVMTI interface, this is a fatal error. | |
*/ | |
printf("ERROR: Unable to access JVMTI Version 1 (0x%x)," | |
" is your J2SE a 1.5 or newer version?" | |
" JNIEnv's GetEnv() returned %d\n", | |
JVMTI_VERSION_1, res); | |
return JNI_OK; | |
} | |
/* Here we save the jvmtiEnv* for Agent_OnUnload(). */ | |
jvmti_agent = boost::shared_ptr(new Darkfall::JVM::JVMTIAgent(jvm, jvmti)); | |
jvmtiCapabilities jvmti_supported_interpreter_capabilities = | |
{ | |
0, // can_tag_objects | |
1, // can_generate_field_modification_events | |
1, // can_generate_field_access_events | |
1, // can_get_bytecodes | |
0, // can_get_synthetic_attribute | |
0, // can_get_owned_monitor_info | |
0, // can_get_current_contended_monitor | |
0, // can_get_monitor_info | |
0, // can_pop_frame | |
1, // can_redefine_classes | |
0, // can_signal_thread | |
1, // can_get_source_file_name | |
1, // can_get_line_numbers | |
1, // can_get_source_debug_extension | |
1, // can_access_local_variables | |
0, // can_maintain_original_method_order | |
1, // can_generate_single_step_events | |
1, // can_generate_exception_events | |
1, // can_generate_frame_pop_events | |
1, // can_generate_breakpoint_events | |
1, // can_suspend | |
1, // can_redefine_any_class | |
0, // can_get_current_thread_cpu_time | |
0, // can_get_thread_cpu_time | |
1, // can_generate_method_entry_events | |
1, // can_generate_method_exit_events | |
1, // can_generate_all_class_hook_events | |
1, // can_generate_compiled_method_load_events | |
0, // can_generate_monitor_events | |
0, // can_generate_vm_object_alloc_events | |
1, // can_generate_native_method_bind_events | |
0, // can_generate_garbage_collection_events | |
0 // can_generate_object_free_events | |
}; | |
error = jvmti->AddCapabilities(&jvmti_supported_interpreter_capabilities); | |
check_jvmti_error(jvmti, error, "Unable to get necessary JVMTI capabilities."); | |
jvmtiEventCallbacks callbacks = {NULL}; | |
memset(&callbacks, 0, sizeof(callbacks)); | |
callbacks.ClassLoad = reinterpret_cast(jvmti_callback_class_load); | |
callbacks.ClassPrepare = reinterpret_cast(jvmti_callback_class_prepare); | |
callbacks.ClassFileLoadHook = reinterpret_cast(jvmti_callback_class_file_load_hook); | |
callbacks.FieldAccess = reinterpret_cast(jvmti_callback_field_access); | |
callbacks.FieldModification = reinterpret_cast(jvmti_callback_field_modification); | |
callbacks.MethodEntry = reinterpret_cast(jvmti_callback_method_entry); | |
callbacks.MethodExit = reinterpret_cast(jvmti_callback_method_exit); | |
callbacks.NativeMethodBind = reinterpret_cast(jvmti_callback_native_method_bind); | |
callbacks.VMDeath = reinterpret_cast(jvmti_callback_vm_death); | |
callbacks.VMInit = reinterpret_cast(jvmti_callback_vm_init); | |
callbacks.VMStart = reinterpret_cast(jvmti_callback_vm_start); | |
//cb.DynamicCodeGenerated = reinterpret_cast(jvmti_callback_dynamic_code_generated); | |
//cb.SingleStep = jvmti_callback_single_step; | |
//cb.Breakpoint = jvmti_callback_breakpoint; | |
//cb.FramePop = jvmti_callback_frame_pop; | |
//cb.Exception = jvmti_callback_exception; | |
//cb.ExceptionCatch = jvmti_callback_exception_catch; | |
//cb.ThreadStart = jvmti_callback_thread_start; | |
//cb.ThreadEnd = jvmti_callback_thread_end; | |
//cb.CompiledMethodLoad = jvmti_callback_compiled_method_load; | |
//cb.CompiledMethodUnload = jvmti_callback_compiled_method_unload; | |
//cb.DataDumpRequest = jvmti_callback_data_dump_request; | |
//cb.MonitorContendedEnter = jvmti_callback_monitor_contended_enter; | |
//cb.MonitorContendedEntered = jvmti_callback_monitor_contended_entered; | |
//cb.MonitorWait = jvmti_callback_monitor_wait; | |
//cb.MonitorWaited = jvmti_callback_monitor_waited; | |
//cb.VMObjectAlloc = jvmti_callback_vm_object_alloc; | |
//cb.ObjectFree = jvmti_callback_object_free; | |
//cb.GarbageCollectionStart = jvmti_callback_garbage_collection_start; | |
//cb.GarbageCollectionFinish = jvmti_callback_garbage_collection_finish; | |
error = jvmti->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks)); | |
check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks"); | |
/* At first the only initial events we are interested in are VM | |
* initialization, VM death, and Class File Loads. | |
* Once the VM is initialized we will request more events. | |
*/ | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_FIELD_ACCESS, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_FIELD_MODIFICATION, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_EXIT, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_NATIVE_METHOD_BIND, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, reinterpret_cast(NULL)); | |
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_START, reinterpret_cast(NULL)); | |
//error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED, reinterpret_cast(NULL)); | |
//error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, reinterpret_cast(NULL)); | |
//error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_SINGLE_STEP, reinterpret_cast(NULL)); | |
//error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, reinterpret_cast(NULL)); | |
check_jvmti_error(jvmti, error, "Cannot set event notification"); | |
/* Here we create a raw monitor for our use in this agent to | |
* protect critical sections of code. | |
*/ | |
//error = jvmti->CreateRawMonitor(jvmti, "agent data", &(gdata->lock)); | |
//check_jvmti_error(jvmti, error, "Cannot create raw monitor"); | |
/* We return JNI_OK to signify success */ | |
return JNI_OK; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment