我正在使用JVMTI编写一个本地Java代理,它遍历所有加载类的所有方法。不幸的是,许多课程似乎还没有准备好,因此
GetClassMethods
退货
JVMTI_ERROR_CLASS_NOT_PREPARED
。我正在注册
ClassPrepare
事件回调,但似乎只对极少数类调用。简化后(减去所有错误处理和释放),我的代码如下所示
JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* jvm, char *options, void *reserved) {
jvmtiEnv *jvmti;
jint class_count;
jclass* classes;
jint method_count;
jmethodID* methods;
(*jvm)->GetEnv(jvm, (void**) &jvmti, JVMTI_VERSION_11);
(*jvmti)->GetLoadedClasses(jvmti, &class_count, &classes);
for (int i = 0; i < class_count; i++) {
jclass klass = classes[i];
// here a lot of time JVMTI_ERROR_CLASS_NOT_PREPARED is returned
jvmtiError err = (*jvmti)->GetClassMethods(jvmti, klass, &method_count, &methods);
}
代理使用JCMD和JVMTI.agent_load命令动态连接到正在运行的JVM。我确实尝试注册了一个类准备回调,使用:
jvmtiEventCallbacks callbacks;
(void)memset(&callbacks, 0, sizeof(callbacks));
callbacks.ClassPrepare = &callbackClassPrepare;
(*jvmti)->SetEventCallbacks(jvmti, &callbacks, (jint) sizeof(callbacks));
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, (jthread) NULL);
但这只适用于极少数课程。
我如何让JVM准备加载的类,以便
GetClassMethods
退货
JVMTI_ERROR_NONE
?
到目前为止,我只使用JDK17.0.1和Shenandoah GC进行了测试。