【读书会第十二期】类加载机制

举报
kentarou 发表于 2022/05/19 18:44:20 2022/05/19
【摘要】 类加载机制

java 是一种类型安全的语言,它有四类称为安全沙箱机制的安全机制来保证语言的安全性,这四类安全
沙箱分别是:
1) 类加载体系
2) .class 文件检验器
3) 内置于 Java 虚拟机(及语言)的安全特性
4) 安全管理器及 Java API

主要讲解类的加载体系:

java 程序中的 .java 文件编译完会生成 .class 文件,而 .class 文件就是通过被称为类加载器的 ClassLoader
加载的,而 ClassLoder 在加载过程中会使用“双亲委派机制”来加载 .class 文件,先上图:

BootStrapClassLoader : 启 动 类 加 载 器 , 该 ClassLoader 是 jvm 在 启 动 时 创 建 的 , 用 于 加载 $JAVA_HOME$/jre/lib 下面的类库(或者通过参数-                                                       Xbootclasspath 指定)。由于启动类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不能直接通过引                                         用进行操作。
ExtClassLoader:扩展类加载器,该ClassLoader是在sun.misc.Launcher里作为一个内部类ExtClassLoader定义的(即 sun.misc.Launcher$ExtClassLoader),                                    ExtClassLoader 会加载 $JAVA_HOME/jre/lib/ext 下的类库(或者通过参数-Djava.ext.dirs 指定)。
AppClassLoader:应用程序类加载器,该 ClassLoader 同样是在 sun.misc.Launcher 里作为一个内部类
                           AppClassLoader 定义的(即 sun.misc.Launcher$AppClassLoader),AppClassLoader 会加载 java 环境变量CLASSPATH 所 指 定 的 路 径 下 的                           类 库 , 而 CLASSPATH 所 指 定 的 路 径 可 以 通 过System.getProperty("java.class.path")获取;当然,该变量也可以覆盖,可以使用参数-cp,例                             如:java -cp 路 径 (可以指定要执行的 class 目录)。


CustomClassLoader:自定义类加载器,该 ClassLoader 是指我们自定义的 ClassLoader,比如 tomcat 的StandardClassLoader 属于这一类;当然,大部分情况下                                 使用 AppClassLoader 就足够了。

前面谈到了ClassLoader的几类加载器,而ClassLoader使用双亲委派机制来加载class文件的。ClassLoader的双亲委派机制是这样的(这里先忽略掉自定义类加载器 CustomClassLoader):

1)当 AppClassLoader 加载一个 class 时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器 ExtClassLoader 去完成。
2)当 ExtClassLoader 加载一个 class 时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader 去完成。
3)如果 BootStrapClassLoader 加载失败(例如在$JAVA_HOME$/jre/lib 里未查找到该 class),会使用ExtClassLoader 来尝试加载;
4)若 ExtClassLoader 也加载失败,则会使用 AppClassLoader 来加载,如果 AppClassLoader 也加载失败,则会报出异常 ClassNotFoundException。

双亲委派托机制为什么安全

举个例子,ClassLoader 加载的 class 文件来源很多,比如编译器编译生成的 class、或者网络下载的字节码。而一些来源的 class 文件是不可靠的,比如我可以自定义一个 java.lang.Integer 类来覆盖 jdk 中默认的 Integer
类,例如下面这样:

初始化这个 Integer 的构造器是会退出 JVM,破坏应用程序的正常进行,如果使用双亲委派机制的话该Integer 类永远不会被调用,以为委托 BootStrapClassLoader 加载后会加载 JDK 中的 Integer 类而不会加载自定义的这个,可以看下下面这测试个用例:

执行时 JVM 并未在 new Integer(1)时退出,说明未使用自定义的 Integer,于是就保证了安全性。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。