类加载器模拟

类版本1

package com.classLoad.version1;

public class Version {
    public void testVersion()
    {
        System.out.println("我是版本1");
    }
}

类版本2

package com.classLoad.version2;

public class Version {
    public void testVersion()
    {
        System.out.println("我是版本2");
    }
}

 

类加载器1

public class ClassLoad_1 extends ClassLoader {
   
     // 读入源文件转换为字节数组 
    private byte[] getSource(String filename) { 
        File file = new File(filename); 
        int length = (int) file.length(); 
        byte[] contents = new byte[length]; 
        FileInputStream fis = null; 
        try { 
            fis = new FileInputStream(file); 
            int r = fis.read(contents); 
            if (r != length) { 
                throw new IOException("IOException:无法读取" + filename); 
            } 
        } catch (FileNotFoundException e) { 
            e.printStackTrace(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } finally { 
            try { 
                if (fis != null) { 
                    fis.close(); 
                } 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
        return contents; 
    } 
 
    // 编译文件 
    public boolean compile(String javaFile) { 
        System.out.println("正在编译" + javaFile); 
        int ret = 0; 
        try { 
            // 调用系统命令编译文件 
            Process process = Runtime.getRuntime().exec("javac " + javaFile); 
            process.waitFor(); 
            ret = process.exitValue(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
        return ret == 0; 
    } 
 
    // 重写findclass 
    @Override 
    protected Class<?> findClass(String name) throws ClassNotFoundException { 
        Class<?> clazz = null; 
        // 将文件的.替换为/,例如com.lyl.reflect.Reflect被替换为com/lyl/reflect/Reflect 
        String fileStub = name.replace(".", "/"); 
        String path =  System.getProperty("user.dir");

        //可以理解为不同路径下的同名类
        fileStub = path + "\\bin\\com\\classLoad\\version1\\" + fileStub;
        // java源文件名 
        String javaFileName = fileStub + ".java"; 
        // 编译后的class文件名 
        String classFileName = fileStub + ".class"; 
        File javaFile = new File(javaFileName); 
        File classFile = new File(classFileName); 
        // 当指定JAVA源文件存在,且class文件不存在, 
        // 或者java源文件的修改时间比class文件修改时间晚则重新编译 
        if (javaFile.exists() 
                && (!classFile.exists() || javaFile.lastModified() > classFile 
                        .lastModified())) { 
            // 如果编译失败,或者class文件不存在 
            if (!compile(javaFileName) || !classFile.exists()) { 
                throw new ClassNotFoundException("ClassNotFoundException:" 
                        + javaFileName); 
            } 
        } 
        // 如果CLASS文件按存在,系统负责将该文件转换成Class对象 
        if (classFile.exists()) { 
            byte[] raw = getSource(classFileName); 
            // 将ClassLoader的defineClass方法将二进制数据转换成Class对象 
            int divindex = name.indexOf("\\"); 
            String javafilename = null; 
            // 如果是某个盘里面的文件,要去掉文件的盘符 
            if (divindex != -1) { 
                javafilename = name.substring(divindex + 1, name.length()); 
            } 
            // 将字节数组转换为class实例 
            clazz = defineClass(javafilename, raw, 0, raw.length); 
        } 
        // 如果clazz为null,表明加载失败,则抛出异常 
        if (clazz == null) { 
            throw new ClassNotFoundException(name); 
        } 
        return clazz; 
    } 
}

类加载器2

public class ClassLoad_2 extends ClassLoader {
   
     // 读入源文件转换为字节数组 
    private byte[] getSource(String filename) { 
        File file = new File(filename); 
        int length = (int) file.length(); 
        byte[] contents = new byte[length]; 
        FileInputStream fis = null; 
        try { 
            fis = new FileInputStream(file); 
            int r = fis.read(contents); 
            if (r != length) { 
                throw new IOException("IOException:无法读取" + filename); 
            } 
        } catch (FileNotFoundException e) { 
            e.printStackTrace(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } finally { 
            try { 
                if (fis != null) { 
                    fis.close(); 
                } 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
        return contents; 
    } 
 
    // 编译文件 
    public boolean compile(String javaFile) { 
        System.out.println("正在编译" + javaFile); 
        int ret = 0; 
        try { 
            // 调用系统命令编译文件 
            Process process = Runtime.getRuntime().exec("javac " + javaFile); 
            process.waitFor(); 
            ret = process.exitValue(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
        return ret == 0; 
    } 
 
    // 重写findclass 
    @Override 
    protected Class<?> findClass(String name) throws ClassNotFoundException { 
        Class<?> clazz = null; 
        // 将文件的.替换为/,例如com.lyl.reflect.Reflect被替换为com/lyl/reflect/Reflect 
        String fileStub = name.replace(".", "/"); 
        String path =  System.getProperty("user.dir");

        //可以理解为不同路径下的同名类

        fileStub = path + "\\bin\\com\\classLoad\\version2\\" + fileStub;
        // java源文件名 
        String javaFileName = fileStub + ".java"; 
        // 编译后的class文件名 
        String classFileName = fileStub + ".class"; 
        File javaFile = new File(javaFileName); 
        File classFile = new File(classFileName); 
        // 当指定JAVA源文件存在,且class文件不存在, 
        // 或者java源文件的修改时间比class文件修改时间晚则重新编译 
        if (javaFile.exists() 
                && (!classFile.exists() || javaFile.lastModified() > classFile 
                        .lastModified())) { 
            // 如果编译失败,或者class文件不存在 
            if (!compile(javaFileName) || !classFile.exists()) { 
                throw new ClassNotFoundException("ClassNotFoundException:" 
                        + javaFileName); 
            } 
        } 
        // 如果CLASS文件按存在,系统负责将该文件转换成Class对象 
        if (classFile.exists()) { 
            byte[] raw = getSource(classFileName); 
            // 将ClassLoader的defineClass方法将二进制数据转换成Class对象 
            int divindex = name.indexOf("\\"); 
            String javafilename = null; 
            // 如果是某个盘里面的文件,要去掉文件的盘符 
            if (divindex != -1) { 
                javafilename = name.substring(divindex + 1, name.length()); 
            } 
            // 将字节数组转换为class实例 
            clazz = defineClass(javafilename, raw, 0, raw.length); 
        } 
        // 如果clazz为null,表明加载失败,则抛出异常 
        if (clazz == null) { 
            throw new ClassNotFoundException(name); 
        } 
        return clazz; 
    } 
}

测试类

public class Test {
    // 定义主方法 
    public static void main(String[] args) throws ClassNotFoundException, 
            SecurityException, NoSuchMethodException, IllegalArgumentException, 
            IllegalAccessException, InvocationTargetException, InstantiationException { 
       
        ClassLoader ccl1 = new ClassLoad_1();
        ClassLoader ccl2 = new ClassLoad_2();
       
        // 加载需要运行的类 
        Class<?> clazz1 = ccl1.loadClass("Version");
        Class<?> clazz2 = ccl2.loadClass("Version");
        Method main1 = clazz1.getMethod("testVersion"); 
        Object o1 = clazz1.newInstance();
        main1.invoke(o1);
        Method main2 = clazz2.getMethod("testVersion"); 
        Object o2 = clazz2.newInstance();
        main2.invoke(o2);
    } 
}

 

输出数据:

我是版本1
我是版本2

 

 

 

你可能感兴趣的:(类加载器)