• 自定义类加载器和父委托机制


    自定义类加载器MyClassLoader

    package com.dwz.classLoader.chapter2;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    
    public class MyClassLoader extends ClassLoader{
        private final static String DEFAULT_DIR = "C:\Users\Administrator\Desktop\classloader1";
        
        private String dir = DEFAULT_DIR;
        
        private String classLoaderName;
    
        public MyClassLoader() {
            super();
        }
        
        public MyClassLoader(String classLoaderName) {
            super();
            this.classLoaderName = classLoaderName;
        }
    
        public MyClassLoader(String classLoaderName, ClassLoader parent) {
            //父委托
            super(parent);
            this.classLoaderName = classLoaderName;
        }
        
        /**
         * @param name (xxx.xxx.xxx.xxx)
         *     xxx/xxx/xxx/xxx.class
         */
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            String classPath = name.replaceAll("\.", "/");
            File classFile = new File(dir, (classPath + ".class"));
            if(!classFile.exists()) {
                throw new ClassNotFoundException("The class " + name + " not found under " + dir);
            }
            
            byte[] classBytes = loadClassBytes(classFile);
            if(null == classBytes || classBytes.length == 0) {
                throw new ClassNotFoundException("load the class " + name + " failed");
            }
            
            return this.defineClass(name, classBytes, 0, classBytes.length);
        }
        
        private byte[] loadClassBytes(File classFile) {
            try(ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    FileInputStream fis = new FileInputStream(classFile)) {
                byte[] buffer = new byte[1024];
                int len;
                while((len = fis.read(buffer)) != -1) {
                    baos.write(buffer, 0, len);
                }
                baos.flush();
                return baos.toByteArray();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        public String getDir() {
            return dir;
        }
    
        public void setDir(String dir) {
            this.dir = dir;
        }
    
        public String getClassLoaderName() {
            return classLoaderName;
        }
    }

    需要加载的目标类

    package com.dwz.classLoader.chapter2;
    
    public class MyObject {
        static {
            System.out.println("My Object static block.");
        }
        
        public String hello() {
            return "Hello World!";
        }
    }

    测试一:

    1.类加载器的委托是优先交给父加载器先去尝试加载
    2.父加载器和子加载器其实是一种包装关系,或者包含关系

         MyClassLoader classLoader1 = new MyClassLoader("MyClassLoader-1");
            Class<?> loadClass = classLoader1.loadClass("com.dwz.classLoader.chapter2.MyObject");
            System.out.println(loadClass);
            System.out.println(loadClass.getClassLoader());
            
            Object obj = loadClass.newInstance();
            Method method = loadClass.getMethod("hello", new Class<?>[] {});
            Object result = method.invoke(obj, new Object[] {});
            System.out.println(result);

    1.先将自动编译好的MyObject.class复制到我们自定义的类加载器文件 DEFAULT_DIR 中

    2.删除自动编译好的MyObject.class文件

    测试二:

    package com.dwz.classLoader.chapter2;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    /**
     *    1.类加载器的委托是优先交给父加载器先去尝试加载
     *    2.父加载器和子加载器其实是一种包装关系,或者包含关系
     */
    public class MyClassLoaderTest {
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
            MyClassLoader classLoader1 = new MyClassLoader("MyClassLoader-1");
            MyClassLoader classLoader2 = new MyClassLoader("MyClassLoader-2", classLoader1);
            Class<?> loadClass = classLoader2.loadClass("com.dwz.classLoader.chapter2.MyObject");
            System.out.println(loadClass);
            System.out.println(((MyClassLoader)loadClass.getClassLoader()).getClassLoaderName());
        }
    }

    父委托机制:
    1.定义类加载器
    2.初始化类加载器
    3.父子类加载器之间的真实关系--包装关系(包含关系)
    4.父委托机制的优点是能够提高系统的安全性,在此机制下,用户自定义的类加载器不可能加载应该有父加载器加载的可靠类,
    因此可以防止恶意的代码代替父加载器的可靠代码

  • 相关阅读:
    《更好的解释(数学篇)》——第一章
    流密码及RC4算法ZZ
    Android
    Android中Handler 、Thread和Runnable之间的关系ZZ
    Android之Handler消息传递机制详解zz
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之四(三十)
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之三(二十九)
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之二(二十八)
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之一(二十七)
    abp(net core)+easyui+efcore实现仓储管理系统——EasyUI之货物管理八(二十六)
  • 原文地址:https://www.cnblogs.com/zheaven/p/12200970.html
Copyright © 2020-2023  润新知