计算机系统应用教程网站

网站首页 > 技术文章 正文

技术进阶:深入浅出Java类加载机制及类加载器关系和变化

btikc 2024-09-08 11:59:09 技术文章 17 ℃ 0 评论

类加载器


简单讲,类加载器ClassLoader的功能就是负责将class文件加载到jvm内存。

类加载器分类


从虚拟机层面讲分为两大类型的类加载器,一是Bootstrap Classloader即启动类加载器(C++实现),它是虚拟机的一部分,二是其他类型类加载器(JAVA实现),在虚拟机外部,并全部继承ClassLoader类。


从细分的角度讲会分为以下三类类加载器:

这是Java 8及之前的类加载器的组成关系。

1、Bootsrap ClassLoader

启动类加载器,完全由jvm控制加载,外面访问不到这个类加载器,即不能被java程序引用。它主要负责加载jvm自身的工作类,即java/lib目录和-Xbootclasspath参数指定的目录的类库。

2、Extension ClassLoader

扩展类加载器,由java实现,即ExtClassLoader实现类。它主要负责加载java/lib/ext目录和系统环境变量java.ext.dirs指定目录所有类库。

3、Application ClassLoader

应用程序类加载器,由java实现,即AppClassLoader实现类。它的父类是ExtClassLoader,它主要负责加载classpath目录上的类库。如果没有自定义ClassLoader,它就是程序中默认的ClassLoader,即可以通过ClassLoader.getSystemClassLoader()获取当前系统的类加载器。


从上图看虽然Bootstrap ClassLoader是最顶层的类加载器,但是不能被程序引用,它也不是ExtClassLoader的父类加载器,ExtClassLoader没有父类载器,我们不防来看下面简单的例子。


程序首先输出了程序默认的类加载器AppClassLoader,然后再输出了其父类加载器ExtClassLoader,然后就完了,这就证实了上面的理论。

类加载机制


虽然定义了上面这几个类加载器,但在加载时类加载器会审查一个class类应该由哪个类型的加载器负责加载,它使用的是等级加载机制,是一种双亲委派模型。

双亲委派模式要求所有类加载器,除了顶层的Bootstrap类加载器之外都要有自己的父类加载器。在收到一个类加载请求时,当前默认的类加载器它不会首先自己来加载这个类,它会委托给自己的父类加载器去加载,父类加载器再委托给父父类加载器,以此类推,直到顶层类加载器,由上到下加载,除非上面的类加载器都无法加载时自己才去加载。

来看看ClassLoader.loadClass方法源码


再回到之前文章中的有一道关于是否可以自定义类java.lang.String并使用的面试题,它在java/lib目录下,所以当应用类加载器去classpath加载时会去委托父类加载器,这时最顶层类加载器会发现自己之前已经加载过,所以这次不再加载,所以自定义的这个java.lang.String虽然可以正常编译,但不能被类加载器加载并使用。

所以,这也是双亲委派模式的好处,同一个路径的类保证不能加载两次,保证了类与类之间的正常行为和正常运行。

Java 9及以后的类加载器组成模式

JDK9保留了三级分层类加载器体系结构,以实现向后兼容。 但是,从模块系统加载类的方式有一些变化。如下 图显示了JDK9类加载器层次结构。

请注意,在JDK9中,应用程序类加载器可以委托给平台类加载器以及引导类加载器; 平台类加载器可以委托给应用程序类加载器。

在JDK9中,引导类加载器在库代码和虚拟机中实现。为了向后兼容,它在程序中仍然由null表示。 例如,Object.class.getClassLoader()仍然返回null。 并非所有Java SE平台和JDK模块都由引导类加载器加载。 仅举几个例子,bootstrap类加载器加载的模块是java.base,java.logging,java.prefs和java.desktop。 其他Java SE Platform和JDK模块由平台类加载器和应用程序类加载器加载,下面将对其进行描述。JDK9不再支持指定引导类路径,-Xbootclasspath和-Xbootclasspath/p以及系统属性sun.boot.class.path的选项。仍支持-Xbootclasspath/a选项,其值存储在系统属性jdk.boot.class.path.append中。

JDK9不再支持扩展机制。 但是,它在名为平台类加载器(platform class loader)的新名称下保留了扩展类加载器。 ClassLoader类包含一个名为getPlatformClassLoader()的新静态方法,它返回平台类加载器的引用。

由于Java从8之后,引入了很重要的一块,即模块系统的支持,整个体系除了兼容以前的模式外,内部做了很大的调整。我们下一篇在仔细讲解一下从Java9开始的新的类加载器的机制和模式吧。

这次就讲这么多了。


本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表