【问题标题】:Stock JDK classes and the "null" ClassLoader?库存 JDK 类和“空”类加载器?
【发布时间】:2021-01-05 18:49:22
【问题描述】:

我正在尝试通过查看ClassLoaders 中的一些动态创建的组件来调试一个非常奇怪的类错误。 ClassLoaders 是我从来没有玩过的东西 - 我很惊讶标准 JDK 类有 null 类加载器实例。

有人可以根据我尝试打印其加载器的类来解释这个简单的 main 方法的输出吗?更一般地说:

  1. ClassLoaders 在 JVM 上的工作方式和
  2. 我们如何使用ClassLoaders 调试缺失的类。
public class MyClass {

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        System.out.println(relfect.MyClass.class.getClassLoader());
        System.out.println(String.class.getClassLoader());
        System.out.println(ArrayList.class.getClassLoader());
        System.out.println(JButton.class.getClassLoader());
        System.out.println(System.class.getClassLoader());

        Boolean b = new Boolean(true);
        System.out.println(b.getClass().getClassLoader());
        
    }

}

输出

sun.misc.Launcher$AppClassLoader@1f7182c1
null
null
null
null
null

【问题讨论】:

  • 这个问题似乎离题了,因为 StackOverflow 不能替代琐碎的 JDK 文档。

标签: java classloader


【解决方案1】:

getClassLoader() 的 javadoc 说

返回类的类加载器。一些实现可能使用 null 来表示引导类加载器。如果此类是由引导类加载器加载的,则此方法将在此类实现中返回 null。

所以,这至少解释了为什么你会得到这个结果。但这并没有解释为什么实施者决定这样做。

编辑: 在测试将我自己的类添加到引导类路径之后,它们也显示为空类加载器。

【讨论】:

  • 谢谢,当您回答以澄清我遇到的更一般的问题时,我正在编辑问题。但无论如何,您的回答很有帮助。
  • @jayunit100 抱歉 ;-) 但是您可以随时发布更多问题。
  • 这是旧功能。我认为这是因为“犯了错误”。一个可能的原因可能是通过返回 null,类不需要存储和/或跟踪类加载器;它只是将 getClassLoader 实现为{ return null }
  • hmmm... 好吧——那么我的类,从源代码,是怎么被默认为 sun "App" ClassLoader 的?
  • @jayunit100 某些类加载器必须加载您的类,如果您还没有实现它,则必须有人执行。此外,空类加载器似乎仅适用于引导类(通常是 JVM 附带的类)。将您自己的类放入引导程序并查看它报告的内容会很有趣。
【解决方案2】:

引导类的类加载器为空,它不是 java 类。

不要误认为类路径中找到的类和引导加载程序加载的类。后者负责通常在 rt.jar 中找到的核心 JDK 类。它是一个原生类加载器,因此没有参考。

类路径上的类由System类加载器加载,可以通过属性指定它的类。

此外,空类加载器被认为是一个安全问题,并且基于具有空类加载器的调用者类进行检查。

【讨论】:

    【解决方案3】:

    这就是它的工作原理。每当 JVM 尝试加载任何类时,它都会检查以下条件。

    如果 Class 是从 Bootstrap ClassPath 加载的,即; jdk\jre\lib\rt.jar , BootStrap ClassLoader 会被调用。

    如果类是从扩展类路径加载的,即; jdk\jre\lib\ext*.jar , Extension ClassLoader 会被调用。

    如果 Class 是从 Application ClassPath 加载的,即;正如环境变量中指定的那样,应用程序类加载器被调用。

    由于 Bootstrap ClassLoader 未在 java 中实现,它要么在 c 或 c++ 中实现,因此没有对它的引用,这就是它返回 null 的原因。但是 Extension 和 Application 类加载器是用 java 编写的,因此您将获得 sun.misc.Launcher$ExtClassLoader@someHexValue 和 sun.misc.Launcher$AppClassLoader@someHexValue 的引用。

    因此,如果您执行类似 System.out.println(String.class.getClassLoader()) 的操作,您将得到 null,因为该类是由 BootStrap ClassLoader 调用的,另一方面,如果您对Ext 或 App Class 路径中的类,您将分别获得 $ExtClassLoader@someHexValue 和 sun.misc.Launcher$AppClassLoader@someHexValue 。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-24
      • 1970-01-01
      • 2017-03-11
      • 1970-01-01
      • 2011-12-13
      相关资源
      最近更新 更多