美文网首页
java ClassLoader 双亲委派

java ClassLoader 双亲委派

作者: LiuJP | 来源:发表于2019-01-15 10:16 被阅读0次

    能自己练习一次就能更深入的了解ClassLoader
    https://blog.csdn.net/briblue/article/details/54973413

    public class ClassLoaderTest {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            ClassLoader cl = ClassLoaderTest.class.getClassLoader();
    
            // cl = int.class.getClassLoader();
            //
            // System.out.println("ClassLoader is:"+cl.toString());
            System.out.println("ClassLoader is:" + cl.toString());
            System.out.println("ClassLoader\'s parent is:" + cl.getParent().toString());
            System.out.println("ClassLoader\'s grand father is:" + cl.getParent().getParent().toString());
        }
    }
    
    

    运行结果:

    ClassLoader is:sun.misc.Launcher$AppClassLoader@4e25154f
    ClassLoader's parent is:sun.misc.Launcher$ExtClassLoader@33909752
    Exception in thread "main" java.lang.NullPointerException
        at ClassLoaderTest.main(ClassLoaderTest.java:14)
    // ExtClassLoader 没有父类ClassLoader
    

    Class 中的final ClassLoader 是jvm 虚拟机初始化时候

    public final class Class<T> implements java.io.Serializable,
                                  GenericDeclaration,
                                  Type,
        /*
         * Private constructor. Only the Java Virtual Machine creates Class objects.
         * This constructor is not used and prevents the default constructor being
         * generated.
         */
        private Class(ClassLoader loader) {
            // Initialize final field for classLoader.  The initialization value of non-null
            // prevents future JIT optimizations from assuming this final field is null.
            classLoader = loader;
        }
    }
    

    ClassLoader.java

    public abstract class ClassLoader {
    
    // The parent class loader for delegation
    // Note: VM hardcoded the offset of this field, thus all new fields
    // must be added *after* it.
    private final ClassLoader parent;
    // The class loader for the system
        // @GuardedBy("ClassLoader.class")
    private static ClassLoader scl;
    
    private ClassLoader(Void unused, ClassLoader parent) {
        this.parent = parent;
        ...
    }
    protected ClassLoader(ClassLoader parent) {
        this(checkCreateClassLoader(), parent);
    }
    protected ClassLoader() {
        this(checkCreateClassLoader(), getSystemClassLoader());
    }
    public final ClassLoader getParent() {
        if (parent == null)
            return null;
        return parent;
    }
    public static ClassLoader getSystemClassLoader() {
        initSystemClassLoader();
        if (scl == null) {
            return null;
        }
        return scl;
    }
    
    private static synchronized void initSystemClassLoader() {
        if (!sclSet) {
            if (scl != null)
                throw new IllegalStateException("recursive invocation");
            sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
            if (l != null) {
                Throwable oops = null;
                //通过Launcher获取ClassLoader
                scl = l.getClassLoader();
                try {
                    scl = AccessController.doPrivileged(
                        new SystemClassLoaderAction(scl));
                } catch (PrivilegedActionException pae) {
                    oops = pae.getCause();
                    if (oops instanceof InvocationTargetException) {
                        oops = oops.getCause();
                    }
                }
                if (oops != null) {
                    if (oops instanceof Error) {
                        throw (Error) oops;
                    } else {
                        // wrap the exception
                        throw new Error(oops);
                    }
                }
            }
            sclSet = true;
        }
    }
    }
    

    我们可以看到getParent()实际上返回的就是一个ClassLoader对象parent,parent的赋值是在ClassLoader对象的构造方法中,它有两个情况:
    1. 由外部类创建ClassLoader时直接指定一个ClassLoader为parent。
    2. 由getSystemClassLoader()方法生成,也就是在sun.misc.Laucher通过getClassLoader()获取,也就是AppClassLoader。直白的说,一个ClassLoader创建时如果没有指定parent,那么它的parent默认就是AppClassLoader。

    我们主要研究的是ExtClassLoader与AppClassLoader的parent的来源,正好它们与Launcher类有关,我们上面已经粘贴过Launcher的部分代码

    public class Launcher {
        private static Launcher launcher = new Launcher();
        private static String bootClassPath =
            System.getProperty("sun.boot.class.path");
    
        public static Launcher getLauncher() {
            return launcher;
        }
    
        private ClassLoader loader;
    
        public Launcher() {
            // Create the extension class loader
            ClassLoader extcl;
            try {
                extcl = ExtClassLoader.getExtClassLoader();
            } catch (IOException e) {
                throw new InternalError(
                    "Could not create extension class loader", e);
            }
    
            // Now create the class loader to use to launch the application
            try {
                loader = AppClassLoader.getAppClassLoader(extcl);
            } catch (IOException e) {
                throw new InternalError(
                    "Could not create application class loader", e);
            }
    
            //设置AppClassLoader为线程上下文类加载器,这个文章后面部分讲解
            Thread.currentThread().setContextClassLoader(loader);
        }
    
        /*
         * Returns the class loader used to launch the main application.
         */
        public ClassLoader getClassLoader() {
            return loader;
        }
        /*
         * The class loader used for loading installed extensions.
         */
        static class ExtClassLoader extends URLClassLoader {}
    
    /**
         * The class loader used for loading from java.class.path.
         * runs in a restricted security context.
         */
        static class AppClassLoader extends URLClassLoader {}
    

    双亲委托

    这里写图片描述

    怎么绕过双亲委派?

    关注微信公众号

    相关文章

      网友评论

          本文标题:java ClassLoader 双亲委派

          本文链接:https://www.haomeiwen.com/subject/bkuedqtx.html