打破双亲委派机制有什么用_打破双亲委派【JVM:类加载机制深度剖析】 - 第9篇...

本文在文章底部有配套学习视频

前言

我们上面分析了tomcat通过打破双亲委派机制实现了隔离性。那我们自己要怎么实现呐。

一、如何打破双亲委派机制

那我们分析下我们这个MyClassLoaderTest这个加载类的过程:

(1)从main的classLoader.loadClass()进行加载我们指定的类。

Class clazz = classLoader.loadClass("com.kfit.jvm.User1");System.out.println(clazz.getClassLoader().getClass().getName());

(2)loadClass调用的是父类的Classload.loadClass(name,resolve):

protected Class> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}

这里的代码关注如果c=null的时候,就会使用parent的loadClass(),如果最终parent为null的话,那么就使用bootstrapclass loader。

MyClassLoaderTest的的parent会是哪个呐?

大家可以使用debug下,可以看到是ExtClassLoader:

AppClassLoader在去找父类ExtClassLoader:

这个就是我们之前讲过的双亲委派加载机制。

特别注意:在启动的时候,会先执行加载AppClassLoader去加载jvm核心的一些类库,所以debug的时候,要注意观察当前使用的是哪个类加载器,加载的哪个类。

通过上面的分析如果我们要打破双亲委派机制,那么可以重写loadClass()方法。

二、自定义加载器打破双亲委派机制

我们来看下MyClassLoaderTest2,我们通过重写loadClass()打破了双亲委派机制。

protected Class> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();//需要系统类从系统类进行加载.if("java.lang.Object".equals(name)){Class> clazz = null;ClassLoader system = getSystemClassLoader();try {c = system.loadClass(name);} catch (Exception e) {// ignore}}//从自己的类加载进行加载.if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}}

运行看下结果:

使用了我们自己定义的类加载,但是好像也不能看出打破了双亲加载呐?可以作如下测试:1)在我们的应用中复制一个com.kfit.jvm.User1的类,(1.1)然后运行,发现还是使用的:MyClassLoaderTest2$MyClassLoader(1.2)注释掉我们的上面的loadClass代码,在运行,那么结果是:Launcher$AppClassLoader

(2)尝试去加载:java.lang.String:

会报错:

java.lang.SecurityException: Prohibited package name: java.lang

上面的测试说明我们确实打破了双亲委派机制,另外还说明了一点就是对于JDK核心的类是被保护的,所在包是被禁止的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值