Skip to content

Instantly share code, notes, and snippets.

@nidefawl
Created September 24, 2015 19:33
Show Gist options
  • Save nidefawl/fe7a718e5950b069172d to your computer and use it in GitHub Desktop.
Save nidefawl/fe7a718e5950b069172d to your computer and use it in GitHub Desktop.
JNI agent example
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