• 双亲委派模型


    类加载流程

    类加载流程,先加载Bootstrap ClassLoader 启动类加载即最顶层的加载类。这部分由C++ 编写。
    继续再次加载Extention ClassLoader 扩展类加载器由Bootstrap ClassLoader加载,加载进入内存。
    继续再次加载Application ClassLoader 应用类加载器,即系统即在此,加载当前应用下的类
    最后再次加载ClassLoader类

    双亲委派模型

    该模型是先检查指定名称的类是否已经加载过,如果加载进入内存,不加载直接返回,如果没有加载过,判断是否有父类加载器,如果拥有父类加载器,那么将会直接将权利移交给父类,由父类代理当前类进行加载该类。或者是调用C++的bootstrap类加载器来加载该类
    最后如果三者都没有找到类,那么直接调用当前类加载器的findClass方法来完成类加载。
    即,如果需要需要加载自定义的类,那么就需要重写findClass方法。

    即,如果需要将当前类加载进入,那么就需要重写findClass方法,若未找到这几种类,则会自动调用findClass方法。

    调用过程

    先加载父类,若父类未加载,继续调用父类,直到bootstrap查看是否已经加载,如果此时都未加载类,那么将会使用自定义的ClassLoader 然后调用自定义的ClassLoader的findClass方法,用于将字节码加载进入内存。最后返回该class的描述符

    栗子

    public class Test {
        public void helloWorld(){
            System.out.println("me loader" + getClass().getClassLoader().getClass());
            // 先调用getClass获取当前类的对象的描述,然后再次调用getClassLoader()获取加载的父类,再次调用getClass()获取加载进入的父类的名称
        }
    }
    
    

    此时如果该类这这个项目里的里的话,会由Application加载当前应用类下的类。

    由类的加载过程可知,当未找到类的时候,会加载类的ClassLoader类,此时需要定义一个类,让该类继承ClassLoader类,由于该类是ClassLoader的子类,此时会自动加载该类,由于该类不在内存当中,所以需要使用static,让其一开始加载进入内存当中。
    代码如下

    import java.io.FileInputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class Main {
        // 需要使用static让其加载进入内存
        static class myClassLoader extends ClassLoader{
            private String classPath;  // 获取当前类的在磁盘中保存的地址
            // 通过构造函数将地址注入
            public myClassLoader(String classPath){
                this.classPath = classPath;
            }
            // 将文件内容加载进入内存
            private byte[] loadByte(String name) throws Exception{
                // 获取一个输入流,
                FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
                // 获取长度
                int len = fis.available();
                // 定义byte数组
                byte[] data = new byte[len];
                // 加载进入内存
                fis.read(data);
                // 关闭流
                fis.close();
                return data;
            }
            // 重写findClass方法,让加载的时候调用findClass方法
            protected Class<?> findClass(String name) throws ClassNotFoundException{
                try{
                    // 读取文件到数组中
                    byte[] data = loadByte(name);
                    // 将字节码加载进入内存当中
                    return defineClass(name, data, 0, data.length);
                }catch(Exception e){
                    e.printStackTrace();
                }
                return null;
            }
        }
        public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
            // 先初始化该类
            myClassLoader classLoader = new myClassLoader("/home/ming");
            // 此时会调用findClass加载Test.class加载进入内存当中
            Class clazz = classLoader.loadClass("Test");
            // 实例化该类对象
            Object obj = clazz.newInstance();
            // 获取clazz该类方法中名称为hello,参数为空的方法。
            Method helloMethod = clazz.getDeclaredMethod("helloWorld", null);
           // 调用该方法
            // 调用obj类中的helloMethod,参数为空的方法。
           helloMethod.invoke(obj, null);
    
        }
    }
    
    

    实验结果

    me loaderclass Main$myClassLoader
    
    Process finished with exit code 0
    

    https://www.iming.info/shuang-qin-wei-pai-mo-xing/

    在无知的道路上缓步前行
  • 相关阅读:
    调用外部文件(ShellExecute)
    字体函数 -- GetDeviceCaps
    字体函数 -- EnumFonts
    字体函数 -- EnumFontFamilies
    回调函数 EnumFontFamProc
    AlphaBlend
    c# 编程修改 wince 系统时间
    windows 打开文件夹
    C# wince 实现软件忙鼠标状态改变
    CSDN第一期总结之三:Thread的问题(转)
  • 原文地址:https://www.cnblogs.com/melovemingming/p/10301736.html
Copyright © 2020-2023  润新知