双亲委派机制

2021-04-21  本文已影响0人  小方块886

为什么设计双亲委派机制:
1.沙箱保护机制,保护jre包下的核心类不被其他加载器创建,只能由自己的引导类加载器创建
2.保证类只有一个,不被重复创建

手写一个自定义加载器:需要继承ClassLoader并且重写findClass方法

public class MyClassLoadTest{

    static class MyclassLoad extends ClassLoader{
        private String path;

        public MyclassLoad(String path){
            this.path = path;
        }

        private byte[] loadByte(String name) throws Exception {
            name = name.replaceAll("\\.", "/");
            FileInputStream fis = new FileInputStream(path + "/" + name + ".class");
            int len = fis.available();
            byte[] data = new byte[len];
            fis.read(data);
            fis.close();
            return data;
        }

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            try {
                byte[] data = loadByte(name);
                return defineClass(name, data, 0, data.length);
            }catch (Exception e){
                e.printStackTrace();
                throw new ClassNotFoundException();
            }
        }

    }


    public static void main(String[] args) throws ClassNotFoundException {
        MyclassLoad myclassLoad = new MyclassLoad("D:/test");
        Class<?> loadClass = myclassLoad.loadClass("com.example.demotrading.bean.CancelOrderTask");
        String name = loadClass.getClassLoader().getClass().getName();
        System.out.println(name);
    }

}

如果需要打破双亲委派机制,需要重写loadClass方法,需要注意的是我们自定义的加载器的父加载器是应用类程序加载器,那么我们只需要在loadClass方法中,不使用parent.loadClass(name, false) 这个方法,就可以理解为打破双亲委派机制

类加载器核心方法

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;
            }
        }

重写loadClass方法:

        @Override
        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 (name.startsWith("com.example.demotrading")){
                        // 自定义搜索文件并加载
                        c = findClass(name);
                    }else {
                        // 有些核心类库的类还是必须要交给父加载器加载
                        c = this.getParent().loadClass(name);
                    }

                    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;
            }
        }
上一篇下一篇

猜你喜欢

热点阅读