Java Demo示例:实现动态编译的demo

本文介绍了在Java中如何使用JavaCompiler API进行动态编译,以及通过Runtime类执行编译和运行Java程序的方法。示例代码展示了如何利用JavaCompiler的StandardJavaFileManager进行文件管理优化,以及如何通过Runtime.exec执行命令行编译和运行class文件。此外,还提到了使用ClassLoader加载和运行class文件的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、使用JavaCompiler

        位于javax.tools的JavaCompiler类提供了从程序调用 Java™ 编程语言编译器的接口。

        编译器可能会在编译期间生成诊断信息(例如,错误消息)。 如果提供了诊断侦听器,则诊断将提供给侦听器。 如果未提供侦听器,则诊断将被格式化为未指定的格式并写入默认输出,即 System.err,除非另有说明。 即使提供了诊断侦听器,某些诊断也可能不适合诊断,并将被写入默认输出。

        编译器工具有一个关联的标准文件管理器,它是工具本机(或内置)的文件管理器。 标准文件管理器可以通过调用getStandardFileManager 获得。

        重用文件管理器可以潜在地减少扫描文件系统和读取 jar 文件的开销。 尽管可能不会减少开销,但标准文件管理器必须与多个顺序编译一起使用。

        这使得以下示例成为推荐的编码模式:

File[] files1 = ... ; // input for first compilation task
File[] files2 = ... ; // input for second compilation task
  
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
  
Iterable<? extends JavaFileObject> compilationUnits1 = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files1));
compiler.getTask(null, fileManager, null, null, null, compilationUnits1).call();
  
Iterable<? extends JavaFileObject> compilationUnits2 =
             fileManager.getJavaFileObjects(files2); // use alternative method
// reuse the same file manager to allow caching of jar files
compiler.getTask(null, fileManager, null, null, null, compilationUnits2).call();
  
fileManager.close();

2、通过Runtime CMD编译

        每个 Java 应用程序都有一个 Runtime 类的实例,它允许应用程序与运行应用程序的环境进行交互。 当前运行时可以从 getRuntime 方法中获取。

        ProcessBuilder.start() 和 Runtime.exec 方法创建本机进程并返回 Process 子类的实例,该实例可用于控制进程并获取有关它的信息。 Process 类提供了执行来自进程的输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀死)进程的方法。

Runtime runtime=Runtime.getRuntime();
Process process=runtime.exec("java -cp D:/skydance hello");
InputStream inputStream=process.getInputStream();
BufferedReader fBufferedInputStream=new BufferedReader(new InputStreamReader(inputStream));
String string="";
while((string=fBufferedInputStream.readLine())!=null)
{
    System.out.println(string);
}

3、运行class

 (1)Runtime CMD

        通过Runtime进行java命令的执行,运行我们动态编译出来的class。

String runCmd = String.format("java -classpath %s %s", WORK_DIR, CLASS);

Process process = Runtime.getRuntime().exec(runCmd);

int exitCode = process.waitFor();

(2)通过ClassLoader

        类加载器是负责加载类的对象。 ClassLoader 类是一个抽象类。 给定类的二进制名称,类加载器应该尝试定位或生成构成类定义的数据。 一种典型的策略是将名称转换为文件名,然后从文件系统中读取该名称的“类文件”。

class NetworkClassLoader extends ClassLoader {
    String host;
    int port;
  
    public Class findClass(String name) {
        byte[] b = loadClassData(name);
        return defineClass(name, b, 0, b.length);
    }
  
    private byte[] loadClassData(String name) {
        // load the class data from the connection
        . . .
    }
}

(3)参考代码

java_example/dynamic compile at main · bashendixie/java_example · GitHubContribute to bashendixie/java_example development by creating an account on GitHub.https://github.com/bashendixie/java_example/tree/main/dynamic%20compile

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坐望云起

如果觉得有用,请不吝打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值