`

类加载器模拟

    博客分类:
  • Java
 
阅读更多

类版本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

 

 

 

分享到:
评论

相关推荐

    PE加载器源码.rar

    PE加载器源码.rar

    powermock源码学习 支持模拟静态方法、构造函数、final类和方法、私有方法以及移除静态初始化器的模拟工具

    PowerMock的核心功能在于其能够通过提供定制的类加载器和应用一些字节码操作技巧,实现对静态方法、构造方法、私有方法和final方法的模拟。例如,在进行单元测试时,有时候我们并不希望测试数据进入实际的数据库,...

    MRAS_LOAD_EI_Centro.zip_EI centro_mras_伺服加载系统_作动器 模拟

    一种实现地震模拟的MRAS系统,能够加载到伺服作动器中。

    风扰模拟力加载器控制系统设计 (2013年)

    针对用于风扰模拟的力加载器系统,设计以DSP为核心的数字控制器。在传统的位置伺服控制的基础上,设计力反馈控制回路,同时使用前馈补偿抑制由于承载对象运动而导致的多余力。使用粒子群算法进行控制器参数整定。试验...

    类膜片加载同轴低阻渡越时间振荡器模拟研究

    提出了一种类膜片加载的同轴低阻渡越时间振荡器,器件的提取腔采用了类膜片加载的扩展互作用腔结构,具有束波作用效率高,电子束空间电荷压力小等优点。提取腔的电场结构为7pi/5模,与传统的类pi结构相比,提高了...

    单元测试模拟框架PowerMock.zip

    通过提供定制的类加载器以及一些字节码篡改技巧的应用,PowerMock 现了对静态方法、构造方法、私有方法以及 Final 方法的模拟支持,对静态初始化过程的移除等强大的功能。因为 PowerMock 在扩展功能时完全采用和被...

    vue+原生模拟手机端横向滚动到底部加载更多或跳转及滚动回弹效果.rar

    vue+原生模拟手机端横向滚动到底部加载更多或跳转及滚动回弹效果。可用于移动端专题展示,横向懒加载等功能。

    power mockito学习资料

    PowerMock使用一个自定义类加载器和字节码操作来模拟静态方法,构造函数,final类和方法,私有方法,去除静态初始化器等等。通过使用自定义的类加载器,简化采用的IDE或持续集成服务器不需要做任何改变。熟悉...

    大流量安全阀实验台液压系统设计与冲击加载模拟

    为对大流量安全阀的性能进行分析和测试,设计了一种大流量安全阀的能器快速加载实验系统,并采用数值模拟方法研究液压系统的动态性能.采用AMESim搭建了实验台的液压系统模型,根据液压系统工作过程中的冲液阶段、加载...

    行业资料-交通装置-一种可模拟车辆转向的偶合器加载驱动桥测试装置.zip

    行业资料-交通装置-一种可模拟车辆转向的偶合器加载驱动桥测试装置.zip

    imgloader:简单的资源加载进度模拟

    一个简单的图片资源加载器。兼容性{ PC: [IE9+,Chrome,FireFox] , Mobile: [] }version"0.2.0":增加音频/视频文件的加载"0.2.1":增加 CMD,AMD 引用"0.2.2":修复 音频/视频文件 replay时 触发imgLoaded事件的BUG...

    虚拟驱动模拟实验

    验要求:1、使用内存模拟字符设备,实现读、写、定位的字符设备驱动程序; 2、编写应用程序、测试驱动; 实验器材: 软件:安装fedora8的系统; 硬件:PC机一台。 设计过程: 1、编写驱动程序memdev.c,实现读、写...

    制动器试验台中模拟负载的新方法

    惯性式制动器试验台均是利用飞轮的惯性能模拟制 动器的负载。这种模拟方法存在以下问题:(1)需用 很多片飞轮}试验台的体积庞大;操作麻烦。(2)对制 动器的垂直制动工况不能模拟。(3)在运行中,不能 改变负载。为此,...

    建立UPS逆变器模型模拟瞬间动态响应特性

    此环路有助于对加载后的输出有效值电压进行补偿。 (3)自动零点校正环路 如图2虚线围成的方块所示,此环路的主要目的是利用分流器检测出流经变压器原边的电流反馈后对零点加以校正,以避免变压器因存在直流分量而...

    C# 模拟键盘操作

    在您的代码中,要加载驱动程序,请调用(阅读下面的代码注释;您必须设置过滤模式以捕获按键事件或发送按键操作!): Input input = new Input(); // Be sure to set your keyboard filter to be able to capture ...

    VB.NET 模拟操作系统

    这个系统可以加载不同应用(前提是有人提供) 这也算是这个系统最大的骄傲了吧 可以说部分做出了智能系统的感觉 大家如果没事的话也可以自己写 OS snv 系统的应用程序 它实际上是一个动态链接库文件 只是改名为 ...

    纯CSS3模拟谷歌Loading加载动画

    解压密码:RJ4587 我们已经为大家分享过很多基于纯CSS3的Loading加载动画了,大部分都是一些简单的几何图形组合而成的循环播放动画,...今天给大家带来另外一款模拟谷歌的纯CSS3 Loading加载动画,一共有6种动画效果。

    node-loader:本机模块的节点加载器

    节点加载器 加载器。 允许连接具有.node扩展名的本机节点模块。 :warning: node-loader仅适用于node / electron-main / electron-main目标。 入门 首先,您需要安装node-loader : $ npm install node-loader --...

    注入加载器::syringe::package:Webpack加载器,用于通过其依赖关系将代码注入模块

    :syringe: :package: inject-loaderWebpack加载器,用于通过依赖关系将代码注入模块为什么这对于编写测试(在执行之前有时需要在被测模块内部进行模拟)的测试特别有用。 inject-loader灵感来自引入的思想,并。用法...

Global site tag (gtag.js) - Google Analytics