【问题标题】:In Java, is it possible to know whether a class has already been loaded when using the bootstrap loader?在Java中,使用引导加载程序时是否可以知道一个类是否已经加载?
【发布时间】:2020-08-06 22:51:35
【问题描述】:

这是In Java, is it possible to know whether a class has already been loaded? 的变体。我们的应用程序执行字节码检测并使用 -Xbootclasspath/a: 选项来检测 Java 运行时。我想知道一个类是否已通过引导加载程序加载——而不是尝试加载它。

如果类是由引导加载程序加载的,则引用查询中列出的代码将不起作用 - 因为我不相信有任何方法可以获取引导加载程序的实例以在调用中使用。

有什么想法吗?我怀疑是做不到的。这对我们的应用程序并不重要,但我很好奇。

【问题讨论】:

  • 我也很好奇这个。代码执行时系统类加载器是否还不可用?
  • “我们的应用程序执行字节码检测”是否意味着您正在实现 Java 代理?
  • 是的,我们有一个实现 ClassFileTransformer 的 Java 代理。

标签: java classloader


【解决方案1】:

当您想要执行运行时字节码检测时,您应该使用 the Instrumentation API 实现 Java 代理。

当参数类型被声明为(String agentArgs, Instrumentation inst) 时,Java 代理将在其premainagentmain 方法中获得一个Instrumentation 实例。

此 API 允许在运行时使用 appending jar files to the bootstrap class path,因此您无需依赖在命令行中指定的 -Xbootclasspath/a 选项。

此外,它还有getAllLoadedClasses()getInitiatedClasses(ClassLoader) 方法来查询已加载的类。因此,您可以使用getInitiatedClasses(null) 来获取引导加载程序当前加载的所有类。您必须对它们进行迭代并自己比较名称,以找出包含的特定类是否是数组。

【讨论】:

    【解决方案2】:

    好吧,疯狂的想法。

    您可以在您描述的线程中使用相同的技术,尝试不同的方法。类ClassLoader有如下方法:

    private Class<?> findBootstrapClassOrNull(String name)
    

    此方法调用原生方法:

    private native Class<?> findBootstrapClass(String name)
    

    您也可以尝试使其易于访问。

    编辑:我尝试了以下代码,但从应用程序类加载器运行:

    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 调用受保护的方法时留下了它。)

    无论我提供什么类,在我的 main 方法运行时,似乎几乎所有内容都已加载,不确定。从“findBootstrapClass”方法的源代码中,我看到了这个:

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

    因此,除非您在检测代码时得到不同的运行结果,否则我认为这可能是不可行的。

    注意:同样,我查看的源代码适用于 OpenJDK 1.8

    祝你好运。

    【讨论】:

    • 调用此方法时似乎每个类都已加载的原因是此方法将加载该类。正如其文档注释所说,如果尚未找到该类,它将仅返回 null
    猜你喜欢
    • 1970-01-01
    • 2012-08-31
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 2023-03-08
    • 2012-12-05
    • 2017-01-26
    • 1970-01-01
    相关资源
    最近更新 更多