首页 > 编程知识 正文

双亲委派机制面试题,打破双亲委派机制的场景

时间:2023-05-05 08:33:31 阅读:15616 作者:3008

父母委托机制在加载类时,一级一级地向上委托,判断是否已经加载,从自定义类加载器——“APP应用程序类加载器”——“扩展类加载器”中启动类加载器,并

双亲委托有个弊端:

不能下放,不能不下放

怎么打破双亲委派机制:(也就是能向下委派和不委派)

自定义类加载器(不委托)

spi机制(向下委托) ) ) ) ) ) ) ) )。

打破父母委托打破父母委托的两种方法:

1 .通过SPI机制,使用服务加载器. load加载

2 .自定义类加载器,继承类加载器,重写load类方法

SPI机制SPI机制是一种服务发现机制。 通过在ClassPath路径下的META-INF/services文件夹中搜索文件,自动加载文件中定义的类。 此机制允许许多框架扩展,例如在JDBC中使用SPI机制。

为什么通过spi机制就能打破双亲委托?

这是因为在某些情况下,父类加载器需要子类加载器加载class文件。 由于加载范围的限制,父加载器无法加载到所需的文件中。

以驱动程序接口为例,驱动程序管理器是从Bootstrap ClassLoader加载的,而com.mysql.jdbc.Driver是从应用程序类loader加载的由于父代委托模型,因此父代加载器无法获取由子代加载器加载的类。 在这种情况下,必须启动类加载器以请求子类加载驱动程序实现,这会破坏父母的委托。

SPI机制demo :

publicinterfacehelloservice { public字符串getname (; }公共类hello 1实施hello服务{ @ overridepublicstringgetname (} { return ' hello1'; } public class hello2implements hello服务{ @ overridepublicstringgetname (} { return ' hello2'; 在main方法中加载时,它使用服务加载器加载

publicclassspitest { publicstaticvoidmain (字符串[ ] args ) serviceloaderhelloserviceserviceloader=service loader.load for }}配置文件,文件名为接口的完整路径,文件内容为实现类的完整路径,例如,我的为com.chuan.service.Hello1

输出结果: hello1

因为只配置了Hello1,所以只找到了一个此实现类。

自定义类加载器实现逻辑:自定义类继承classLoader,以自定义类加载器的形式重写loadClass方法,不执行父母委托逻辑,从而破坏父母委托。

看看不可重写的demo

结果:

sun.misc.launcher $ app class loader @ 58644 d46

发现是APP类加载器。

然后重写loadClass方法

publicclassmyclassloaderextendsclassloader { publicstaticvoidmain (字符串[ ] args ) throwsclassnotfoundexception (/ser可视度) aclass=my class loader.load class (test1.class.getname ) ); 系统. out.println (aclass.getclass loader () ); }保护类? findclass(stringclassname ) throwsclassnotfoundexception (system.out.println ) ' myfindclass!' ); 返回空值; }保护类? load{ Class(stringname,boolean resolve ) throwsclassnotfoundexception (synchronized ) getclassloadinglock (name ) ) ) classne if(c==null ) { long t0=System.nanoTime; 修改try{//classloader的原始父母委托逻辑,使其成为父母委托if(name.startswith('com.Chuan ' ) ) c=findclass (查找类) name ); } else { c=this.getParent ().loadclass(name ); }catch(classnotfoundexceptione ) ) if ) c==null ) { long t1=System.nanoTime ); c=查找类(name ); sun.misc.perfcounter.getparentdelegationtime ().addtime ) T1-T0 ); sun.misc.perfcounter.getfindclasstime ().addelapsedtimefrom ) ) T1; sun.misc.perfcounter.getfindclasses ().increment ); } if (求解) )求解类) c; }返回c; } }}class Test1{ }执行错误。 无法加载此类,因为它未委托给app类加载器。

那么又来了新问题。如果我自定义类记载器和核心类重名怎么办,该怎么加载,又或者我想篡改核心类内容,jvm又是怎么解决的?

jvm一定解决了这个问题。 openjdk的源代码位于AccessController.doPrivileged

学名是沙箱安全机制

demo :

package java.lang; public class integer { publicstaticvoidmain (string [ ] args ) system.out.println('1' ); }执行错误:

错误在:类java.lang.Integer中找不到main方法。 请将main方法定义为3360

publicstaticvoidmain (字符串[ ] args ) )。

否则,Java FX APP应用程序类必须扩展javafx.application.Application

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。