什么是双亲委派机制?如何打破双亲委派机制?
JVM的双亲委派机制知道吗?怎么打破它呢?你看看自己掌握的怎么样呢?
什么是双亲委派机制?(父类委托机制)
- 检查某个类是否已经加载
自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个Classloader已加载,就视为已加载此类,保证此类只所有ClassLoader加载一次。 - 加载的顺序
自顶向下,也就是由上层来逐层尝试加载此类。父类加载,子类不加载。
面试的过程中你能把上面的说出来我觉得刚刚及格,如果你能将下面JVM的三种机制也告诉面试官,我觉得,你这个小伙子有前途!
补充扩展:JVM的三种类加载机制
- 全盘负责 :就是当一个类加载器负责加载某 个Class 时,该 Class 所依赖的和引用的其他 Class 也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入
- 父类委托 :就是当一个类加载器负责加载某个Class时,先让父类加载器试图加载该 Class ,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类
- 缓存机制 :保证所有加载过的 Class 都会被缓存,当程序需要使用某个 Class 对象时,类加载器先从缓存区中搜索该 Class ,只有当缓存区中不存在该 Class对象 时,系统才会读取该类对应的二进制数据,并将其转换成 Class对象 ,存储到缓存区
如何打破双亲委派机制?
- 通过自定义类加载器,继承classloader,重写loadclass方法;
- 通过SPI机制,使用ServiceLoader.load去加载,SPI Service Provider Interface 服务提供接口 意味着他的拓展性很强;
打破双亲委派机制的案例?
打破双亲委派机制的场景有很多:JDBC、JNDI、Tomcat等等,这块展开来说就比较多了,感兴趣的同学可以先自行学习,后续我们会专门讲一讲这个怎么Tomcat打破双亲委派的典型案例。
什么是SPI机制呢?
SPI机制是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。这一机制为很多框架扩展提供了可能,比如在SpringBoot中就使用到了SPI机制。
沙箱机制
我们创建一个自定义string类,但是在加载自定义String类的时候会率先使用引导类加载器加载,而引导类加载器在加载的过程中会先加载jdk自带的文件(rt.jar包中java\lang\String.class),报错信息说没有main方法,就是因为加载的是rt.jar包中的string类。这样可以保证对java核心源代码的保护,这就是沙箱安全机制。
双亲委派机制的优势
- 双亲机制可以避免类的重复加载
- 沙箱机制保护程序安全,防止核心API被随意篡改
自定义类:java.lang.String(报错:阻止创建 java.lang开头的类)
双亲委派机制的缺点
- 优势很突出,问题也比较明显,检查类是否加载的委托过程是单向的,这个方式虽然从结构上说比较清晰,使各个ClassLoader的职责非常明确,但是同时会带来一个问题,即顶层的ClassLoader无法访问底层的ClassLoader所加载的类。
结论:
- 由于Java虚拟机规范并没有明确要求类加载器的加载机制一定要使用双亲委派机制,只是建议而已。
- 比如在Tomcat中,类加载器所采用的加载机制就和传统双亲委派模型有一定区别,当缺省的类加载器接收到一个类的加载任务时,首先会由它自行加载,当它加载失败时,首先会由它自行加载,当它加载失败时,才会将类的加载任务委派给它的超类加载器去执行,这同时也是Servlet规范推荐的一种做法。