Hi Charlie,
It is hard to say what is wrong from the information you provided.
I agree with Mikael the following lines look incorrect:
assert(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)) ==
JVMTI_ERROR_NONE);
assert(jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, nullptr) == JVMTI_ERROR_NONE);
I guess, they won't be executed in the release/product mode.
So, you may want to replace the asserts which normal checks (working in
any mode) of the returned values.
In general, your code does what is needed to enable the CFLH events.
Q1:
if (res != JNI_OK || jvmti==nullptr) {
fprintf(stderr,"Unable to get JVMTI!");
}
Do you see the above is printed in the output?
I'd also recommend to add more tracing to make sure everything is
executed as you expect.
Good luck with your project!
Thanks,
Serguei
On 1/11/21 05:59, Daniel D. Daugherty wrote:
Redirecting to the serviceability-dev@... alias since JVM/TI is
maintained
by the Serviceability team...
Dan
On 1/10/21 6:09 PM, Mikael Vidstedt wrote:
Just a control question: Are you *sure* asserts are actually enabled?
Having actual application logic in an assert is normally a bad idea
because if/when you compile the release/production version with
asserts disabled the application behavior will change.
Cheers,
Mikael
On Jan 10, 2021, at 8:33 AM, Charlie <[email protected]> wrote:
Hi,
I have a working jvmti agent on Linux (Java(TM) SE Runtime
Environment (build 1.8.0_271-b09)) that hooks the class load event.
This same agent compiled for windows claims to work (all asserts
pass), but my hook never gets called, is anyone able to tell me why?
I register my callback like so:
jint res = vm->GetEnv(reinterpret_cast<void **>(&jvmti),
JVMTI_VERSION_1);
if (res != JNI_OK || jvmti==nullptr) {
fprintf(stderr,"Unable to get JVMTI!");
}
assert(res == JVMTI_ERROR_NONE);
jvmtiCapabilities capabilities = {0};
capabilities.can_retransform_classes=1;
capabilities.can_generate_all_class_hook_events = 1;
assert(jvmti->AddCapabilities(&capabilities) == JVMTI_ERROR_NONE);
jvmtiEventCallbacks callbacks;
memset(&callbacks,0,sizeof(callbacks));
callbacks.ClassFileLoadHook = &class_file_load_hook_handler;
assert(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks))
== JVMTI_ERROR_NONE);
assert(jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, nullptr) == JVMTI_ERROR_NONE);
The callback itself is as follows:
static void JNICALL class_file_load_hook_handler(
jvmtiEnv* jvmti,
JNIEnv* env,
jclass class_being_redefined,
jobject loader,
const char* name,
jobject protection_domain,
jint class_data_len,
const unsigned char* class_data,
jint* new_class_data_len,
unsigned char** new_class_data
) {
if (name == nullptr) {
return;
}
printf("loaded %s\n",name);
}
(to clarify, all JNI functions in the lib work fine)
The Windows machine's java version string is this:
java version "1.8.0_271"
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)