【JVM】类加载器:双亲委派机制、沙箱安全机制
· 双亲委派机制、沙箱安全机制是JVM中类加载器系统的相关术语
· 在这之前,应该先了解JVM类加载器系统的相关概念
一、类加载器基础知识
见下图1,java文件首先会被编译成class文件,class文件作为Java虚拟机的可识别文件,编译完成后,需要加载到内存。
我们针对不同的class文件,会相应用到不同的类加载器。
· 引导类加载器:Bootstrap ClassLoader,也叫做启动类加载器/根类加载器,并不继承ClassLoader类。引导类加载器使用C/C++语言实现,在Java创立初期,C/C++在速度上占据优势,所以引导类加载器嵌套在JVM内部,用来加载Java核心类库,为Java加速。
· 扩展类加载器:Extension ClassLoader,继承了ClassLoader类。上层类加载器为引导类加载器。负责加载JRE的扩展目录,从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK系统安装目录的jre/lib/ext子目录(扩展目录)下加载类库。如果用户创建的jar放在此目录下,也会自动由扩展类加载器加载。
· 系统类加载器:Application ClassLoader,也叫做应用程序类加载器,继承了ClassLoader类。系统类加载器主要加载日常开发中开发者自己编写的类。
· 自定义类加载器(狭义):User-Defined ClassLoader,继承了ClassLoader类。狭义上的自定义类加载器,是开发人员自定义的一类加载器。但是从广义上来说,官方在Java虚拟机中规定将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器。
所以说(参考上图1),扩展类加载器、系统类加载器、自定义类加载器(狭义)都算作自定义类加载器。
注意,各个加载器是没有继承关系的,途中的箭头只是逻辑上的一种理解。
二、双亲委派机制
核心解释:
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
举个例子:
假设我们在项目工程中写一个类叫做java.lang.Integer
,此类在加载的时候,由于是我们自己写的,它对应的类加载器是系统类加载器,然后由于双亲委派机制,向上沿此路线传递:系统类加载器 --> 拓展类加载器 --> 启动类加载器,到了启动类加载器的时候,加载了核心类库中的java.lang.Integer
。这样就防止了核心类被篡改,也可以防止类被重复加载。
得出双亲委派机制的优点:
由上例:
1、安全,可避免用户自己编写的类动态替换Java的核心类,如java.lang.String。,java核心api中定义类型不会被随意替换,假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。
2、避免全限定命名的类重复加载(使用了findLoadClass()判断当前类是否已加载)。Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次
三、沙箱安全机制
核心解释:
主要用来防止恶意代码污染java源代码。
自定义String类,但是在加载自定义String类的时候会率先使用引导类加载器加载,而引导类加载器在加载的过程中会先加载jdk自带的文件(rt.jar包中javalangString.class),报错信息说没有main方法就是因为加载的是rt.jar包中的String类。这样可以保证对java核心源代码的保护,这就是沙箱安全机制。
相关文章
- Java要抛弃祖宗的基业,Java程序员危险了!
- 十大 Java 语言特性
- JVM 三色标记算法,原来是这么回事!
- 聊聊 Spring 事务控制策略以及 @Transactional 失效问题避坑
- 写给 Java 程序员的前端 Promise 教程
- 写给 Java 程序员的前端 Promise 教程,你学会了吗?
- Java 中为什么不全部使用 Static 方法?
- Java 池化技术你了解多少?
- Java 服务 Docker 容器化优秀实践
- Spring Boot + EasyExcel导入导出,简直太好用了!
- 我们一起聊聊 Java 内存泄漏
- CentOS 下安装 Docker 极简教程
- JDK 19 功能集冻结:Java 19 只有七个新特性
- 关于 CMS 垃圾回收器,你真的懂了吗?
- 为什么会有这么多编程语言?
- 改善Java代码的八个建议
- 接口流量突增,如何做好性能优化?
- Java 以编程方式创建JAR文件
- POJO、Java Bean是如何定义的
- Spring 的 Bean 明明设置了 Scope 为 Prototype,为什么还是只能获取到单例对象?