美文网首页
【Java基础】动态编译

【Java基础】动态编译

作者: 灰色孤星 | 来源:发表于2018-10-22 11:04 被阅读0次

源代码:https://gitee.com/AgentXiao/reflection
动态编译要点:
1、使用场景(在线代码测评)
2、动态编译的两种方式
3、动态运行编译好的文件的两种方式

一、使用场景

在程序运行过程中,需要再次编译其他的程序。比如在线测评系统,要求在线对java文件进行编译和运行。

二、实现动态编译

动态编译的实现有两种做法:
1、通过Runtime调用javac,启动新的进程去操作。

Runtime run = Runtime.getRuntime();
Process process = run.exec("javac d:/test/test.java"); 

2、通过JavaCompiler动态编译。

/**
 * @ClassName Demo01
 * @Description 测试动态编译
 * @Author xwd
 * @Date 2018/10/21 21:42
 */
public class Demo01 {
    public static void main(String[] args) {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        int result = compiler.run(null,null,null,"D:/test/a.java");
        System.out.println(result == 0 ? "编译成功" : "编译失败");
    }
}

由于文件名为a.java,但是定义了public class test,这是错误的,因此:

编译失败

将文件名修改为test.java后编译成功,生成了class文件。

编译成功生成class文件

三、动态运行编译好的类

1、通过Runtime.getRuntime()运行启动新的进程运行

/**
 * @ClassName Demo03
 * @Description 动态运行编译好的类
 * @Author xwd
 * @Date 2018/10/22 10:44
 */
public class Demo03 {
    public static void main(String[] args) throws IOException {
        Runtime run = Runtime.getRuntime();
        //run.exec("javac d:/test/test.java");
        Process process = run.exec("java -cp d:/test/ test");

        BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String info = "";
        while((info = br.readLine()) != null){
            System.out.println(info);
        }

    }
}

2、通过反射运行编译好的类

/**
 * @ClassName Demo04
 * @Description 通过反射运行编译好的类
 * @Author xwd
 * @Date 2018/10/22 10:52
 */
public class Demo04 {
    public static void main(String[] args) throws Exception {
        runJavaClassByReflect("D:/test/","test");
    }

    public static void runJavaClassByReflect(String dir,String classFile) throws Exception{
        try {
            //通过url获得Class类对象
            URL[] urls = new URL[] {new URL("file:/"+dir)};
            URLClassLoader loader = new URLClassLoader(urls);
            Class c = loader.loadClass(classFile);
            //调用加载类的main方法(必须使用Object转型)
            c.getMethod("main",String[].class).invoke(null,(Object)new String[]{});
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这里需要注意的是:
由于可变参数是JDK1.5之后才有的,因此在

c.getMethod("main",String[].class).invoke(null,(Object)new String[]{"aa","bb"});

中,如果不加(Object)进行强制转型的话,编译器会编译成:

.invoke(null,"aa","bb");

但是main方法的参数是字符串数组,会发生不匹配问题。

错误参数个数异常

因此必须使用(Object)进行强制转型,避免这个问题。

相关文章

  • 【Java基础】动态编译

    源代码:https://gitee.com/AgentXiao/reflection动态编译要点:1、使用场景(在...

  • Java基础:反射

    反射注解动态代理相关阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 ...

  • Java基础:注解

    系列阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 1. 概述 注解...

  • Java基础:动态代理

    系列阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 概述 在运行时,...

  • Java基础:类加载器

    系列阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 1. 什么是类加...

  • Java动态编译那些事

    jdk1.6中添加了编译API, 我们可以在java代码中调用编译API动态编译JAVA源文件, 也就是运行时编译...

  • Java的动态机制---动态编译

    Java的动态机制---动态编译1 作用 客户写代码,动态编译。 服务器动态加载某些类文件 2 两种做法 通过Ru...

  • Java环境变量实例

    Java 实例 - 如何编译 Java 文件 我们在Java基础中已经讲过了如何编译java文件。 javac 命...

  • 动态编译基础

    一. 将函数或方法放在文本文件或dll文件或字符串中,可以修改添加后,直接使用主程序调用改变后的功能。(把方法和主...

  • java 动态编译

    为了更深入的了解动态代理,手动实现一下动态代理,其中涉及动态编译的东西,记录一下入门点推荐先看这个文章 Java ...

网友评论

      本文标题:【Java基础】动态编译

      本文链接:https://www.haomeiwen.com/subject/ldpizftx.html