一篇文章带你深入理解 Java 中的Class.getClassLoader
文章目录一、ClassLoader 的作用二、ClassLoader 层次结构三、Class 加载时调用类加载器的顺序一、ClassLoader 的作用我们都知道java程序写好以后是以.java(文本文件)的文件存在磁盘上,然后,我们通过(bin/javac.exe)编译命令把.java文件编译成.class文件(字节码文件),并存在磁盘上。但是程序要运行,首先一定要把.class文件加载...
一、ClassLoader 的作用
我们都知道java程序写好以后是以.java
(文本文件)的文件存在磁盘上,然后,我们通过(bin/javac.exe)编译命令把.java
文件编译成.class
文件(字节码文件),并存在磁盘上。
但是程序要运行,首先一定要把.class
文件加载到JVM内存中才能使用的,我们所讲的classLoader,就是负责把磁盘上的.class
文件加载到JVM内存中,如下图所示:
你可以认为每一个Class对象拥有磁盘上的那个.class
字节码内容,每一个class对象都有一个getClassLoader()
方法,得到是谁把我从.class
文件加载到内存中变成Class对象的
二、ClassLoader 层次结构
(1)根类加载器(null)
它是由本地代码(c/c++)实现的,你根本拿不到他的引用,但是他实际存在,并且加载一些重要的类,它加载(%JAVA_HOME%\jre\lib)
,如rt.jar(runtime)、i18n.jar
等,这些是Java的核心类。
(2)平台类加载器(PlatformClassLoader)(jdk1.8之后的版本,之前的称为扩展类加载器 ExtClassLoader)
虽说能拿到,但是我们在实践中很少用到它,它主要加载扩展目录下的jar包, %JAVA_HOME%\lib\ext
(3)应用类加载器(appClassLoader)
它主要加载我们应用程序中的类,如Test,或者用到的第三方包,如jdbc驱动包等。这里的父类加载器与类中继承概念要区分,它们在class定义上是没有父子关系的。
三、Class 加载时调用类加载器的顺序
当一个类要被加载时,有一个启动类加载器和实际类加载器的概念,这个概念请看如下分析:
如上面的Test.class
要进行加载时,它将会启动应用类加载器进行加载Test
类,但是这个应用类加载器不会真正去加载它,而是会调用看是否有父加载器,结果有,是扩展类加载器,扩展类加载器也不会直接去加载,它看自己是否有父加载器没,结果它还是有的,是根类加载器。
所以这个时候根类加载器就去加载这个类,可在%JAVA_HOME%\jre\lib
下,它找不到dir_b.Test
这个类,所以他告诉他的子类加载器,我找不到,你去加载吧,子类扩展类加载器去%JAVA_HOME%\lib\ext
去找,也找不着,它告诉它的子类加载器 AppClassLoader,我找不到这个类,你去加载吧,结果AppClassLoader找到了,就加到内存中,并生成Class对象。
这个时间时候启动类加载器(应用类加载器)和实际类加载器(应用类加载器)是同一个.
这也是 Java 中著名的委托加载机制:
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)