Почему jvm отправляет несколько событий jvmti classload для одного и того же класса?

Я включил события JVMTI ClassLoad, которые должны генерироваться при первой загрузке класса. Я ожидал получить это событие ровно один раз для каждого загруженного класса, но для некоторых классов оно создается несколько раз, например. это я получаю дважды:

ClassLoad: Ljava/util/concurrent/ThreadFactory; loaded by thread 1
ClassLoad: Ljava/util/concurrent/ThreadFactory; loaded by thread 1

В systemDictionary.cpp я обнаружил три появления JvmtiExport::post_class_load, которые, как я полагаю, являются кодом, ответственным за выполнение обратного вызова (если есть). Они в

  1. SystemDictionary::resolve_instance_class_or_null
  2. SystemDictionary::parse_stream
  3. SystemDictionary::define_instance_class

Но я еще не понимаю всего потока и, следовательно, не понимаю, почему я получаю событие несколько раз.

Могу ли я что-нибудь сделать, чтобы предотвратить это, или мне нужно позаботиться об этом самому и настроить код, чтобы игнорировать более одного события для одного и того же класса?

0
0
138
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это нормально увидеть событие дважды. Это означает, что разрешение класса происходит дважды в контексте разных загрузчиков классов. Сначала это разрешается загрузчиком классов Bootstrap, затем загрузчиком классов System - sun.misc.Launcher.AppClassLoader.

Утилита от этот ответ проливает свет на обстоятельства, при которых происходят такие события.

Рассмотрим простой пример:

public class Test {

    public void setThreadFactory(ThreadFactory factory) {
    }

    public static void main(String[] args) {
    }
}

Когда средство запуска ищет public static void main(), оно создает объекты Method для общедоступных методов, и это вызывает разрешение всех классов в сигнатурах таких методов.

Первое событие ClassLoad:

Class loaded: java/util/concurrent/ThreadFactory
  - ClassLoad(_jvmtiEnv*, JNIEnv_*, _jobject*, _jclass*) + 0x69
  - JvmtiExport::post_class_load(JavaThread*, Klass*) + 0x15b
  - SystemDictionary::define_instance_class(instanceKlassHandle, Thread*) + 0x3cc
  - SystemDictionary::find_or_define_instance_class(Symbol*, Handle, instanceKlassHandle, Thread*) + 0x35d
  - SystemDictionary::load_instance_class(Symbol*, Handle, Thread*) + 0x20c
  - SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle, Handle, Thread*) + 0x78c
  - JVM_FindClassFromBootLoader + 0x22b
  - Java_java_lang_ClassLoader_findBootstrapClass + 0x9b
  * java/lang/ClassLoader.findBootstrapClass @ -1
  * java/lang/ClassLoader.findBootstrapClassOrNull @ 12
  * java/lang/ClassLoader.loadClass @ 48
  * java/lang/ClassLoader.loadClass @ 38
  * sun/misc/Launcher$AppClassLoader.loadClass @ 81
  * java/lang/ClassLoader.loadClass @ 3
  * java/lang/Class.getDeclaredMethods0 @ -1
  * java/lang/Class.privateGetDeclaredMethods @ 37
  * java/lang/Class.privateGetMethodRecursive @ 2
  * java/lang/Class.getMethod0 @ 16
  * java/lang/Class.getMethod @ 13
  * sun/launcher/LauncherHelper.validateMainClass @ 12
  * sun/launcher/LauncherHelper.checkAndLoadMain @ 214

Второй:

Class loaded: java/util/concurrent/ThreadFactory
  - ClassLoad(_jvmtiEnv*, JNIEnv_*, _jobject*, _jclass*) + 0x69
  - JvmtiExport::post_class_load(JavaThread*, Klass*) + 0x15b
  - SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle, Handle, Thread*) + 0x87c
  - SystemDictionary::resolve_or_fail(Symbol*, Handle, Handle, bool, Thread*) + 0x33
  - get_mirror_from_signature(methodHandle, SignatureStream*, Thread*) + 0xc6
  - Reflection::get_parameter_types(methodHandle, int, oopDesc**, Thread*) + 0x18e
  - Reflection::new_method(methodHandle, bool, bool, Thread*) + 0xfc
  - get_class_declared_methods_helper(JNIEnv_*, _jclass*, unsigned char, bool, Klass*, Thread*) + 0x479
  - JVM_GetClassDeclaredMethods + 0xcb
  * java/lang/Class.getDeclaredMethods0 @ -1
  * java/lang/Class.privateGetDeclaredMethods @ 37
  * java/lang/Class.privateGetMethodRecursive @ 2
  * java/lang/Class.getMethod0 @ 16
  * java/lang/Class.getMethod @ 13
  * sun/launcher/LauncherHelper.validateMainClass @ 12
  * sun/launcher/LauncherHelper.checkAndLoadMain @ 214

Другие вопросы по теме