Мы работаем над Java-агентом JVMTI, который используется для обработки файлов классов Java. Небольшая его часть (очевидно) является собственным кодом C ++, но большей частью является код Java, который загружается по сети и вызывается из собственного кода агента.
Мы используем инструмент покрытия кода для сбора тестового покрытия для части Java, которая выполняет инструментарий исходного кода.
Теперь, когда наш агент запускается, некоторые классы инициализируются, в частности, java.lang.ref.Reference, который запускает Thread. Наш агент использует метод запуска потока с пользовательским Java-кодом, который оснащается инструментом покрытия кода.
Инструмент покрытия помещает некоторые статические внутренние классы со статическими инициализаторами в наш код агента java, поэтому он выполняется в результате инициализации java.lang.ref.Reference.
Проблема в том, что в настоящее время (когда инициализируется java.lang.ref.Reference), некоторые базовые функциональные возможности JVM еще не созданы. В частности, инициализатор инструментов покрытия кода хочет получить доступ к System.getProperty (String name), но System.props по-прежнему равен нулю, поэтому в результате вызова возникает исключение NullPointerException.
Это приводит к тому, что статический внутренний класс инструмента покрытия кода остается неинициализированным, класс находится в состоянии initialization_error, результатом является NoClassDefFoundError. Каждый последующий доступ к этому классу приводит к NoClassDefFoundError.
Мое намерение теперь состоит в том, чтобы проигнорировать эту первоначальную ошибку инициализации и подождать до VM_Start, а затем сбросить ClassState рассматриваемого класса в «связанный». Таким образом, я надеюсь, что JVM попытается снова инициализировать класс при последующих обращениях к классу.
У кого-нибудь есть идея, если это можно сделать из агента JVMTI, и дайте мне несколько советов, как это можно сделать?