java 动态编译运行
创始人
2024-04-12 09:53:09

文章目录

  • 写在前面
    • 1、Java Compiler
      • 1.1、java文件编译成class文件
        • run 编译
        • exec 执行指令
      • 1.2、字符串编译成class文件
      • 1.3、工具类

写在前面

Java Compiler 可以动态执行一段字符串形式的java代码,或手动编译java文件。

1、Java Compiler

1.1、java文件编译成class文件

run 编译

D:\Test.java 文件内容:

public class Test {public static void main(String[] args) {int i = 0;System.out.println("test run "+i);}
}

把java文件编译成class文件

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();int result = compiler.run(null, null, null, "D:\\Test.java");   // 在 D:\\Test.java 同目录下,会出现Test.class文件System.out.println(result == 0 ? "编译成功" : "编译失败");

exec 执行指令

exec 执行指令,等同于在cmd中输入指令

        // 执行java命令,空参数,所在文件夹Process process = Runtime.getRuntime().exec("java Test", null, new File("F:\\demo\\"));BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));String str;while ((str = bufferedReader.readLine()) != null) {System.out.println(str);    // 这里打印的是控制台输出的}

如上代码,等同于在cmd输入:java Test

在这里插入图片描述

1.2、字符串编译成class文件

新建类 StringObject,代表字符串java对象内容

package com.kaka;import javax.tools.SimpleJavaFileObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;// 必须继承自SimpleJavaFileObject 
public class StringObject extends SimpleJavaFileObject {private String content = null;protected StringObject(String className, String contents) throws URISyntaxException {super(new URI(className), Kind.SOURCE);this.content = contents;}@Overridepublic CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {return content;}
}

编译java字符串

package com.kaka;import javax.tools.*;
import java.net.URISyntaxException;
import java.util.Collections;public class Test01 {public static void main(String[] args) throws URISyntaxException {// 要编译的字符串,这个字符串必须是一个类String contents = "package com.kaka;" +"class Test {\n" +"    public static void main(String[] args) {\n" +"\tint i = 0;\n" +"        System.out.println(\"测试运行 \"+i);\n" +"    }\n" +"}";JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null, null, null);JavaFileObject testFile = new StringObject("com.kaka.Test", contents);JavaCompiler.CompilationTask task = javaCompiler.getTask(null, standardJavaFileManager, null, null, null, Collections.singletonList(testFile));if(task.call()){System.out.println("success");}else{System.out.println("failure!");}}
}

1.3、工具类

将1.1和1.2总结为一个工具类

package com;import javax.tools.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;public class JavaCodeUtil {/** java字符串代码,转为class文件 **/public static String codeToClass(String code,String compilePath) {String className = getClassNameFromCode(code);JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null, null);JavaFileObject stringObject = new StringObject(className, code);// compilePath 指定编译的class文件的路径List options = Arrays.asList("-d", compilePath);JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, null, options, null, Collections.singletonList(stringObject));if(task.call()){// 从code第一行读出包名String packageName = getPackageNameInFirstLine(code);String classFileName = className + "." + "class";return compilePath + "/" +  packageName + "/" + classFileName;}else{return null;}}public static String javaToClass(String fileName,String compilePath) throws IOException {JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null, null);Iterable fileObjects = fileManager.getJavaFileObjects(fileName);// compilePath 指定编译的class文件的路径List options = Arrays.asList("-d", compilePath);JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, null, options, null, fileObjects);if(task.call()){// 从文件第一行读包名File sourceFile = new File(fileName);BufferedReader bufferedReader = new BufferedReader(new FileReader(sourceFile));String line;while ((line = bufferedReader.readLine()) != null) {if (line.startsWith("package")) {break;}}String packageName = line;packageName = packageName.replaceAll("package", "").trim().replaceAll("\\.", "/");packageName = packageName.substring(0, packageName.length() - 1);// 获取类名(这里简单处理, 默认文件名与类名相同)String sourceFileName = sourceFile.getName();String[] split = sourceFileName.split("\\.");String simpleClassName = split[0] + "." + "class";return compilePath + "/" +  packageName + "/" + simpleClassName;}else{return null;}}public static class StringObject extends SimpleJavaFileObject {private final String content;public StringObject(String className, String contents) {super(URI.create(className), Kind.SOURCE);this.content = contents;}@Overridepublic CharSequence getCharContent(boolean ignoreEncodingErrors){return content;}}/** 根据java文件第一行获取包名 */public static String getPackageNameInFirstLine(String code){return code.substring(0,code.indexOf(";")).replace("package ", "").replaceAll("\\.", "/");}/** 从java String字符串中获取类名 */public static String getClassNameFromCode(String code){int classBlank = code.indexOf("class ")+6;String className = code.substring(classBlank);int nextBlank = className.indexOf(" ");className = className.substring(0,nextBlank);if(className.contains("{")){int i = className.indexOf("{");className = className.substring(0,i);}return className;}/** 获取项目根目录 */public static String getProjectPath() {String path = JavaCodeUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath();if (System.getProperty("os.name").contains("dows")) {path = path.substring(1);}if (path.contains("jar")) {path = path.substring(0, path.lastIndexOf(".")).substring(0, path.lastIndexOf("/"));return path;} else {return path.replace("target/classes/", "");}}
}

测试使用JavaCodeUtil

    public static void main(String[] args) throws ClassNotFoundException {// java代码String contents = "package com.kaka;\n" +"class Test02 {\n" +"    public static void main(String[] args) {\n" +"\tint i = 0;\n" +"        System.out.println(\"这是Test02的main方法 \"+i);\n" +"    }\n" +"   public void getiii(){}\n" +"}";// 把字符串编译成class文件JavaCodeUtil.codeToClass(contents,getProjectPath()+"target/classes");// 加载这个calss文件Class aClass = Class.forName("com.kaka.Test02");// 获取Test02中的方法Method[] methods = aClass.getMethods();for (Method method : methods) {System.out.println(method.getName());}}

相关内容

热门资讯

亿利达诉浙江华昇消防机电安装有... 1月12日消息,天眼查数据显示,近日公布了一则浙江亿利达风机股份有限公司作为原告/上诉人的开庭公告,...
好莱客诉龙湖物业服务集团有限公... 1月12日消息,天眼查数据显示,近日公布了一则广州好莱客创意家居股份有限公司作为原告/上诉人的开庭公...
智通港股通占比异动统计|1月1... 根据2026年1月9日披露数据,中伟新材(02579)、浙江世宝(01057)、纳芯微(02676)...
国泰海通诉广东宜华房地产开发有... 1月12日消息,天眼查数据显示,近日公布了一则国泰海通证券股份有限公司作为原告/上诉人的开庭公告,案...
王炳忠:当台湾人看到大陆才是唯... 转自:北京日报客户端台湾时事评论员王炳忠近日接受北京日报客户端记者专访时表示,台湾年轻人对大陆的看法...