您的位置 首页 java

你真的懂Java类加载器吗?图文详解ClassLoader的原理和机制

什么是ClassLoader

ClassLoad:类加载器用来加载 java 类到 Java 虚拟机中。Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。

jdk中提供了三种类加载器:

  • 引导类加载器BootStrap ClassLoader

  • 扩展类加载器Extension ClassLoader

  • 应用类加载器Application ClassLoader

其中Extension ClassLoader和Application ClassLoader被定义在Launcher类中,BootStrap ClassLoader则是使用 c++ 实现的,在jdk中无法直接找到。

三种类加载器的特点

一般情况下,BootStrap ClassLoader是最上层的类加载器,但是需要注意的是BootStrap ClassLoader并不是任何Classloader的父类加载器,这也是为什么类加载过程称为“双亲”的原因。BootStrap ClassLoader加载的路径可以通过系统属性“sun.boot.class.path”来设置。

Extension ClassLoader加载路径可以通过系统属性“java.ext.dirs”来设置。

Application ClassLoader加载路径可以通过系统属性“java.class.path”来设置,这个属性一般会在启动程序的时候作为一个启动参数来配置。

双亲委派机制

类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,一直委托到最顶层父类加载器,最顶层的父类加载器再把加载任务委托给BootStrap ClassLoader来加载,具体的类加载时序图如下图:

实现这个加载过程的关键代码:

逻辑很简单:如果当前类加载器的父类加载器不为空,就先让父类加载器加载name所对应的类,这里的parent成员变量就是父类加载器。ExtClassLoader的父类加载器是null,就会执行else的逻辑,调用findBootstrapClassOrNull(),而该方法最终为native方法private native Class findBootstrapClass(String name),实际上就是调用openjdk中BootStrap ClassLoader的实现去加载该类。

为什么采用双亲委派机制来加载类?

  • 出于安全考虑。通过双亲委派机制,可以有效的防止系统类被篡改,比如自己写一个java.lang.String类是无法替换掉真正的String类的。

  • 保证了各个类加载器之间的隔离。最常见的就是 tomcat web容器 可以通过定义不同的类加载器实现各个web应用的完全隔离。

双亲委派机制是否可以被绕过?

答案显然是可以的。我们可以通过自定义一个类加载器,并且实现它的loadClass方法,在这个方法中不优先去父类加载器中查找类就可以了。需要注意的是,在ClassLoader中有一个方法:preDefineClass,该方法会用来校验待加载类的信息,比如:java开头的类会直接抛出异常。

所以如果想要真正的绕过双亲委派机制,还需要去掉类似于preDefineClass这样的校验。

文章来源:智云一二三科技

文章标题:你真的懂Java类加载器吗?图文详解ClassLoader的原理和机制

文章地址:https://www.zhihuclub.com/187488.shtml

关于作者: 智云科技

热门文章

网站地图