JVM学习(7)类加器双亲委托机制

本文详细介绍了Java中的类加载器,特别是双亲委托机制。从根类加载器Bootstrap ClassLoader开始,经过Extension ClassLoader和App ClassLoader,直到用户自定义类加载器,解释了类如何被逐级加载。通过代码测试,展示了不同类加载器的加载过程,并分析了getClassLoader()的源代码。
摘要由CSDN通过智能技术生成

类加器双亲委托机制

类加载器

Java当中类加载器的层次体系

  • 根类加载器
  • 扩展类加载器
  • 系统类加载器
  • 用户自定义类加载器

这是有最顶层根类加载器下面一层就是扩展类加载器依此类推。

用户自定义加载器一般都从系统类加载器衍生。

类加载器的父亲委托机制

  • 在父类委托机制中,各个加载器按照父子关系形成了树形结构,除了根类加载器之外其余的加载器都有且只有一个父加载器。
  • 若有一个类加载器能成功加载Test类,那么这个类加载器被称为定义类加载器,所有能成功成功返回Class对象应用的类加载器(包括定义类加载器)都被成为初始类加载器(了解)

如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-akxTM3i1-1581322584387)(E:\Typora\图片\2020-02-10-01.png)]

**双亲委托机制:**loader1想要去加载Sample类,根据类加载器的双亲委托机制不是由loader1加载到Sample类当中,其实它是吧Sample类转交给系统类加载器然后在交给扩展类加载器发现他也有父亲,就会转交给根类加载器然而根类加载器并不能加载。

我们可以看看下面的图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uk7TiDV7-1581322584388)(E:\Typora\图片\2020-02-10-02.png)]

**双亲委托机制:**这里说了根类不能加载失败了Sample类所以他就会返回扩展类加载器尝试加载依此类推,当加载成功就会吧结果返回给loader1

Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader

  • Bootstrap ClassLoader (根类加载器)
    • $JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
  • Extension ClassLoader(扩展类加载器)
    • 负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定吗目录下的jar包
  • App ClassLoader (系统类加载器)
    • 负责加载classpath中指定的jar包及目录中class

接下来我们用代码进行测试

public class MyTest7 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> clazz= Class.forName("java.lang.String");
        System.err.println(clazz.getClassLoader());

    }
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vsbalQ6T-1581322584388)(E:\Typora\图片\2020-02-10-04.jpg)]

这里我们可以看一下.getClassLoader()的源代码定义在Class类当中以及一些英文注释后面都接上中文翻译大家都凭自己的理解

   /**
     * Returns the class loader for the class.  Some implementations may use 返回类的类加载器。一些实现可能使用
     * null to represent the bootstrap class loader. This method will return 空表示引导类装入器。此方法将返回
     * null in such implementations if this class was loaded by the bootstrap 如果此类是由引导程序加载的,则在此类实现中为空
     * class loader. 类加载器
     *
     * <p> If a security manager is present, and the caller's class loader is
     * not null and the caller's class loader is not the same as or an ancestor of 如果存在安全管理器,并且调用方的类加载器是
     * the class loader for the class whose class loader is requested, then 请求其类加载器的类的类加载器,然后
     * this method calls the security manager's {@code checkPermission} 此方法调用安全管理器的{@code checkPermission}
     * method with a {@code RuntimePermission("getClassLoader")} 具有{@code RuntimePermission(“getClassLoader”)的方法
     * permission to ensure it's ok to access the class loader for the class. 权限,以确保可以访问该类的类加载器。
     *
     * <p>If this object 如果这个对象
     * represents a primitive type or void, null is returned. 表示基元类型或void,返回null。
     *
     * @return  the class loader that loaded the class or interface 加载类或接口的类加载器
     *          represented by this object. 由这个对象表示。
     * @throws SecurityException
     *    if a security manager exists and its 如果存在安全管理器及其
     *    {@code checkPermission} method denies {@code checkPermission}方法拒绝
     *    access to the class loader for the class. 访问类的类加载器。
     * @see java.lang.ClassLoader
     * @see SecurityManager#checkPermission
     * @see java.lang.RuntimePermission
     */
    @CallerSensitive
    public ClassLoader getClassLoader() {
        ClassLoader cl = getClassLoader0();
        if (cl == null)
            return null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
        }
        return cl;
    }

​ 这里的clazz输出为null所以是有Bootstrap ClassLoader(根类加载器)$JAVA_HOME中jre/lib/rt.jar里所有的class因为String是rt.jar里面的class文件,大家可以看看这句翻译(null in such implementations if this class was loaded by the bootstrap 如果此类是由引导程序加载的,则在此类实现中为空

更改代码进行测试

public class MyTest7 {
   public static void main(String[] args) throws ClassNotFoundException {
       Class<?> clazz= Class.forName("java.lang.String");
       System.err.println(clazz.getClassLoader());
       Class<?> clazz2= Class.forName("com.jvm.classloader.A");
       System.err.println(clazz2.getClassLoader());//获取类加载器
   }
}


class A {

}

运行结果:

在这里插入图片描述
​ 那么clazz2的输出sun.misc.Launcher$AppClassLoader@73d16e93,AppClassLoader(应用类加载器)系统类加载器这里证明了A的加载器是AppClassLoader接下来我们来看看这个类里面的代码。

 static class AppClassLoader extends java.net.URLClassLoader {
        final sun.misc.URLClassPath ucp;

        public static java.lang.ClassLoader getAppClassLoader(java.lang.ClassLoader classLoader) throws java.io.IOException { /* compiled code */ }

        AppClassLoader(java.net.URL[] urls, java.lang.ClassLoader classLoader) { /* compiled code */ }

        public java.lang.Class<?> loadClass(java.lang.String s, boolean b) throws java.lang.ClassNotFoundException { /* compiled code */ }

        protected java.security.PermissionCollection getPermissions(java.security.CodeSource codeSource) { /* compiled code */ }

        private void appendToClassPathForInstrumentation(java.lang.String s) { /* compiled code */ }

        private static java.security.AccessControlContext getContext(java.io.File[] files) throws java.net.MalformedURLException { /* compiled code */ }
    }

java.security.AccessControlContext getContext(java.io.File[] files) throws java.net.MalformedURLException { /* compiled code */ }
}


这里的是反编译出来的不是源代码AppClassLoader是我们的应用类加载器(系统类加载器)主要负责我们工程当中的class文件,他是间接从ClassLoader衍生展开的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值