JVM:初识类加载器与双亲委派机制

类加载器定义

实现通过类的全限定名获取代表类的二进制流,并生成java.lang.Class对象的这一动作的代码被称为类加载器。

类加载器分类

在这里插入图片描述

通过上图我们可清晰得知类加载器主要分为三种,三种类加载器之间实际是组合关系并不是继承关系:

  1. 启动类加载器BootstrapClassLoader
    由C语言编写的类加载器,也是最顶层的加载器,主要用来加载<JAVA_HOME>\jre\lib下的rt.jar、resourese.jar、charset.jar包里类,可以通过-Xbootclasspath设置加载指定路径中存放的类库。
  2. 扩展类加载器ExtClassLoader
    是存在于launcher中的静态内部类,继承URLClassLoader,是用于加载<JAVA_HOME>\jre\lib\ext下的jar包里的类,可以通过java.ext.dirs系统变量设置加载指定路径中存放的类库。
  3. 应用程序加载器ApplicationClassLoader
    是存在于launcher中的静态内部类,继承URLClassLoader,用于加载用户类路径classpath指定的所有类库。
  4. 自定义类加载器
    非jdk自带的类加载器,是由我们自己通过继承抽象类ava.1ang.ClassLoader类的方式,可以实现自己的类加载器,以满足一些特殊的需求。
    JDK1.2之前,我们总是通过去继承ClassLoader类并重写1oadClass()方法,从而实现自定义的类加载类,但在JDK1.2之后已不再建议用户去覆盖1oadclass()方法,而是建议把自定义的类加载逻辑写在findclass()方法中
    在编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URIClassLoader类,这样就可以避免自己去编写findclass()方法及其获取字节码流的方式,使自定义类加载器编写更加简洁。

双亲委派机制

双亲委派机制释义

当我们加载一个Object.class文件时,首先会在ApplicationClassLoader中检查是否已经加载过,如果有则无需再加载,如果没有则会拿到父加载器,然后调用父类的loadClass()方法,父类加载器也会检查类是否已加载过,如果没有加载再继续往上。直到到达最顶层类加载器BootstrapClassLoader,它上层是不存在父类加载器的,所以它会去尝试加载class类,如果无法加载则下层到子类加载器,子类加载器重复父类加载器的动作,直至ApplicationClassLoader类加载器,如果它也无法加载类,则会抛出ClassNotFoundException异常。
在这里插入图片描述
源码

 public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }
    //              -----??-----
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
            // 首先,检查是否已经被类加载器加载过
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    // 存在父加载器,递归的交由父加载器
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        // 直到最上面的Bootstrap类加载器
                        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.
                    c = findClass(name);
                }
            }
            return c;
    }

双亲委派机制的好处

防止危险代码的注入,比如有人会尝试去替换系统级别的类如String.class,篡改它的代码实现,这种机制就可以很好的扼制这种危险发生,为什么呢?因为String.class已经被BootstrapClassLoader加载过了,那么它的子类加载器不会再去加载被篡改的String类了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值