手动创建一个java.lang.String类,请问这个类是否可以被类加载器加载?

1 答案

不可以。

在 Java 的实现中,类的加载优先由其父类加载器来完成,也就是双亲委托机制

我们自定义的 java.lang.String 类,如下图,在最底层的自定义部分,其父类加载器是 Application ClassLoader,而 Application ClassLoader 的父类加载器是 Extension ClassLoader,Extension ClassLoader 的父类加载器是 Bootstrap ClassLoader:

Bootstrap ClassLoader
 ↑
Extension ClassLoader
 ↑
Application ClassLoader
 ↑
Custom ClassLoader

根据父类加载器优先原则,加载过程会层层向上,最终会在顶部的 Bootstrap ClassLoader 中找到java.lang.String,Bootstrap 加载器将其加载到内存中,忽略自定义 java.lang.String 类。

如果我们自定义一个 com.oomake.String 类,那么在检查过程中,顶部的3个父类加载器都无法加载到它,才会逐层往下最终落到自定义加载器进行加载。

这种双亲委托机制可以有效避免重复加载,当父亲已经加载了该类的时候,子类 ClassLoader 就不会再夹在一次,确保了类的加载安全。

另外,如果自己写 ClassLoader 来加载自定义的java.lang.String 类可不可以呢?

也不可能,因为针对java.*开头的类,JVM 的实现中已经保证了必须由 Bootstrap ClassLoader 来加载。

最后,附上顶部三个类加载器对应所在位置:

  • BootstrapClassLoader(启动类加载器) :最顶层的加载类,由 C++ 实现,负责加载 %JAVA_HOME%/lib目录下的jar包和类或者或被 -Xbootclasspath 参数指定的路径中的所有类。
  • ExtensionClassLoader(扩展类加载器) :主要负责加载目录 %JRE_HOME%/lib/ext 目录下的 jar 包和类,或被 java.ext.dirs 系统变量所指定的路径下的 jar 包。
  • AppClassLoader(应用程序类加载器) :面向我们用户的加载器,负责加载当前应用classpath下的所有 jar 包和类。
xiaobai xiaobai 4 月前 点赞 0