В Java, можно ли узнать, был ли уже загружен класс, при использовании загрузчика bootstrap? - PullRequest
2 голосов
/ 01 августа 2020

Это вариант В Java, возможно ли узнать, был ли уже загружен класс? . Наше приложение выполняет инструментирование байтового кода и использует параметр -Xbootclasspath / a :, чтобы иметь возможность инструментировать среду выполнения Java. Я хотел бы знать, был ли класс загружен с помощью загрузчика bootstrap - без попытки его загрузить.

Код, указанный в указанном запросе, не будет работать, если класс был загружен загрузчиком bootstrap - поскольку я не верю, что есть способ получить экземпляр загрузчика bootstrap для использования в вызове.

Есть мысли? Я подозреваю, что это невозможно. Для нашего приложения это не критично, но мне любопытно.

Ответы [ 2 ]

3 голосов
/ 06 августа 2020

Если вы хотите выполнить инструментирование байтового кода во время выполнения, вы должны реализовать Java-агент, используя Instrumentation API .

Агент Java получит Instrumentation Экземпляр в его методе premain или agentmain, когда его типы параметров были объявлены как (String agentArgs, Instrumentation inst).

Этот API позволяет добавлять файлы jar в bootstrap путь к классам во время выполнения, поэтому вам не нужно полагаться на параметр -Xbootclasspath/a, указанный в командной строке.

Кроме того, у него есть методы getAllLoadedClasses() и getInitiatedClasses(ClassLoader) для запроса уже загруженных классов. Таким образом, вы можете использовать getInitiatedClasses(null), чтобы получить все классы, загруженные в данный момент загрузчиком bootstrap. Вы должны перебирать их и самостоятельно сравнивать имена, чтобы выяснить, является ли конкретный класс содержащимся массивом.

0 голосов
/ 01 августа 2020

Хорошо, безумная идея.

Вы можете использовать ту же технику в описанном вами потоке, попробовав другой метод. Класс ClassLoader имеет следующий метод:

private Class<?> findBootstrapClassOrNull(String name)

Этот метод вызывает собственный метод:

private native Class<?> findBootstrapClass(String name)

Который вы также можете попытаться сделать доступным.

EDIT: I Тем не менее, я пробовал следующий код, запущенный из загрузчика классов приложения:

public class MyClassLoader extends ClassLoader {
    public static void main(String[] args)
            throws NoSuchMethodException,
            InvocationTargetException,
            IllegalAccessException {
        Method method = ClassLoader.class.getDeclaredMethod(
                "findBootstrapClass", String.class);
        method.setAccessible(true);
        MyClassLoader cl = new MyClassLoader();
        System.out.println(method.invoke(cl, "java.lang.String"));
        System.out.println(method.invoke(cl, "sun.java2d.loops.GraphicsPrimitiveMgr$2"));
    }
}

(Кстати, этот код не должен расширять ClassLoader, я просто оставил это из предыдущего теста, где я вызывал защищенный метод из ClassLoader.)

Какие бы классы я ни предоставлял, в момент запуска моего основного метода кажется, что почти все загружено, не уверен. Из исходного кода для метода findBootstrapClass я вижу следующее:

    /**
     * Returns a class loaded by the bootstrap class loader;
     * or return null if not found.
     */
    private Class<?> findBootstrapClassOrNull(String name)

Итак, если вы не получите другой результат во время инструментирования кода, я думаю, возможно, это невыполнимо. .

ПРИМЕЧАНИЕ: опять же, исходный код, который я просмотрел, предназначен для OpenJDK 1.8

Удачи.

...