类加载机制

1、代码从主方法加载到jvm的过程

在这里插入图片描述

2、几种类加载器

引导类加载器(bootStrap):比如这Math.class文件,通过引导类加载器可以帮我们从jre目录下加载一些核心包。
扩展类加载器(ExtClassLoader):加载jre中ext目录相关的类
应用类加载器(AppClassLoader):加载我们的类Math.class,我们的类默认使用AppClassLoader
自定义类加载器:可以继承ClassLoader类,重写findClass方法、loadClass等方法实现自己的类加载器

3、双亲委派机制

几个类加载器之间的关系
这个是类图,不是双亲委派依赖关系
在这里插入图片描述

3.1 双亲委派机制的定义

当我们从主函数进入,加载某个类时,优先选择AppClassLoader加载器进行加载当前类,判断当前类是否已经加载过这个类,若未加载过,则委托其parent属性所对应的加载器进行加载,若最后还是未找到,则会通过使用当前类加载器findClass(name),去找URLClassLoader中的findClass方法,再去本地找。

3.2 双亲委派中的parent关系

自定义类加载器的parent是AppClassLoader
AppClassLoader的parent是ExtClassLoader
ExtClassLoader没有parent属性,这时会走else条件,使用BootStrap方法加载

3.3双亲委派中的parent关系源码

在Launcher的构造器中,分别给AppClassLoader与ExtClassLoader的parent赋了值。
AppClassLoader的parent为var2,也就是ExtClassLoader

        AppClassLoader(URL[] var1, ClassLoader var2) {
            super(var1, var2, Launcher.factory);
            this.ucp.initLookupCache(this);
        }

ExtClassLoader的parent为null

        public ExtClassLoader(File[] var1) throws IOException {
            super(getExtURLs(var1), (ClassLoader)null, Launcher.factory);
            SharedSecrets.getJavaNetAccess().getURLClassPath(this).initLookupCache(this);
        }

3.4 注意

双亲委派机制中的parent并不是真的指其父类,而是parent属性所对应的类

3.5 双亲委派机制核心源码

位置:java.lang.ClassLoader#loadClass(java.lang.String, boolean)

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先,看这个类(name参数所代表的类)是否已经被加载过
            Class<?> c = findLoadedClass(name);
            //若未被加载过,就找其parent属性所对应的加载器
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                	//若这个加载器有parent
                    if (parent != null) {
                    	//使用其parent进行加载
                        c = parent.loadClass(name, false);
                    } else {
                    	//该类没有parent,则直接使用bootstrap寻找,也就是我
                    	//我们所说的,在jre的lib目录下的包中寻找是否有
                        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();
                    //就去urlClassLoader中寻找(当前类加载器本地寻找)
                    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;
        }
    }

3.6 为什么要设计双亲委派机制?

沙箱安全机制:自己写的java.lang.String.class类不会被加载,这样便可以防止核心API库被随意篡改
避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次,保证被加载类的唯一性

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值