2016-08-25 5 views
4

Либо с помощью CustomClassloader, либо с помощью Java-агента + Инструментарий API достаточно прост и прост, чтобы получить все классы, загруженные JVM. Однако список классов, которые были , инициализирован, кажется, не так легко получить. (Я действительно задаюсь вопросом, есть ли способ получить его)Как узнать, был ли класс инициализирован или нет?

Итак, есть ли способ узнать, был ли инициализирован класс?

- Спасибо заранее

+0

Почему вы хотите сделать это? –

+0

У меня есть часть программного обеспечения, которое уже выполняет классы и добавляет определенное статическое поле в каждый класс (который я хотел бы собирать после выполнения программы). поскольку я точно знаю, какие классы были загружены, я могу легко получить это поле путем отражения. однако, если класс X был загружен, но не инициализирован, отражение вызовет статический конструктор класса, который инициализирует все статические переменные и т. д., поэтому, если есть способ узнать, что конкретный класс X не был инициализированный, я даже не попытаюсь получить статическое поле из этого класса. – josecampos

+0

Если у вас уже есть классы инструментов, вы можете добавить статический инициализатор к классам с кодом, который будет их собирать, например 'MyClassesCollector.list.add (MethodHandles.look.add). LookupClass());' Также агенты сервисной службы могут это сделать , но они заморозят целевой процесс. –

ответ

3

Я не уверен, что Instrumentation API, но один из возможных способов является использование JVMTI GetClassStatus функции.

С интерфейсом инструмента вы можете получить все классы, загруженные J и выяснить, не имеющий флаг JVMTI_CLASS_STATUS_INITIALIZED статуса

JavaVM *jvm; 
jvmtiEnv *jvmti; 
jvmtiError err; 

env->GetJavaVM(&jvm); 
jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_2); 

jint classCount = 0; 
jclass * classes; 

jvmti->GetLoadedClasses(&classCount, &classes); 
for (int i = 0; i < classCount; i++) { 
    jint classStatus = 0; 
    jvmti->GetClassStatus(classes[i], &classStatus); 

    if (classStatus != JVMTI_CLASS_STATUS_PRIMITIVE 
     && classStatus != JVMTI_CLASS_STATUS_ARRAY 
     && classStatus != JVMTI_CLASS_STATUS_ERROR 
     && !(classStatus & JVMTI_CLASS_STATUS_INITIALIZED)) { 
     // static initializer is not finished yet 
    } 
} 
+0

большое спасибо за ваш ответ. хотя, похоже, он делает именно то, что мне нужно, я предпочел бы больше решения на Java. просто потому, что будет больно поддерживать разные ОС, разные Archs (32, 64) и т. д. – josecampos

+0

@josecampos Мне кажется, что эта функциональность очень низкоуровневая. Поэтому Java-решение также будет использовать встроенную библиотеку для проверки статусов классов. В любом случае, если вы найдете какое-либо решение, я также буду рад увидеть его :) – vsminkov

Смежные вопросы