双亲委派机制_打破双亲委派【JVM:类加载机制深度剖析】 第9篇

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

47f40e8a2ab0d2a3b5014fc1b6a1a22e.gif

前言

         我们上面分析了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 loaded        Class> 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 stats                sun.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:

2d2bcf357e60c12c93f63ce92323d996.png

         AppClassLoader在去找父类ExtClassLoader:

a9ec8b5e5fcfac557a24c90728126e25.png

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

特别注意:在启动的时候,会先执行加载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 loaded            Class> 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 stats                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);                    sun.misc.PerfCounter.getFindClasses().increment();                }            }            if (resolve) {                resolveClass(c);            }            return c;        }    }}

运行看下结果:

699d2f7a50f02f02275cc395aaad9cac.png

         使用了我们自己定义的类加载,但是好像也不能看出打破了双亲加载呐?可以作如下测试:

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核心的类是被保护的,所在包是被禁止的。

相关历史文章(阅读本文之前,您可能需要先看下之前的系列?)

JVM内存模型和性能调优:为什么要学习JVM - 第1篇

什么是Java虚拟机【JVM:基础入门】 - 第2篇

一图了解JVM核心组成【JVM:基础入门】 - 第3篇

类加载过程【JVM:类加载机制深度剖析】 - 第4篇

深入理解加载和初始化【JVM:类加载机制深度剖析】 - 第5篇

类加载器【JVM:类加载机制深度剖析】 - 第6篇

双亲委派机制【JVM:类加载机制深度剖析】 - 第7篇

打破双亲委派【JVM:类加载机制深度剖析】 - 第8篇 

JVM内存模型和调优实战课程

4e7b6e4dfef92a8aac6f7ed9fd0299a4.png

http://t.cn/A6wWMVqG

点击「阅读原文」快速查看学习:

学习的天平上,你在左盘付出的越多,那么在右盘得到的也会随着你的付出而增多。致敬大师,致敬未来的你。

d394676fedcd1d82f239c1071f39d85d.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值