當時接到一個活, 需要做程序的評測, 前端傳遞java代碼到後端, 後端進行java代碼的評測.
包括java代碼是否能夠編譯運行, 結果是否正確, 程序運行的時間, 以及程序運行佔用的內存的.
這個時候我們就需要使用到java的動態編譯了. 其實首先想到的就是JavaCompiler 這個類了, 可以自己實現一套代碼的編譯邏輯,
但是本着儘量做完的原則, 就不自己造輪子了,這裏有個選擇,
國人, 廖雪峯 他最JavaCompile對了一個簡單的封裝, 打成了jar包, 可以實現一些比較簡單的編譯功能. 試了一下還是蠻好用的.
這裏就不列舉了.
關於java的動態編譯, 我們還可以使用asm 或者 javassit, 這次我們的技術選擇使用javassit, 因爲asm過於複雜, 時間不允許, 暫時也沒有業務場景一定要用到asm,就選擇了相對簡單的javassit了.
下面我們來說下, javassit的簡單使用.
首先需要引入jar包:
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.26.0-GA</version>
</dependency>
package com.onyx.demo;
import javassist.*;
public class Demo{
public static void demo() throws Exception {
ClassPool pool = ClassPool.getDefault();
// 1. 創建一個空類
CtClass cc = pool.makeClass("com.onyx.demo.Person");
// 2. 新增一個字段 private String name;
// 字段名爲name
CtField param = new CtField(pool.get("java.lang.String"), "name", cc);
// 訪問級別是 private
param.setModifiers(Modifier.PRIVATE);
// 初始值是 "chengcheng"
cc.addField(param, CtField.Initializer.constant("chengcheng"));
// 3. 生成 getter、setter 方法
cc.addMethod(CtNewMethod.setter("setName", param));
cc.addMethod(CtNewMethod.getter("getName", param));
// 4. 添加無參的構造函數
CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);
cons.setBody("{name = \"chengcheng\";}");
cc.addConstructor(cons);
// 5. 添加有參的構造函數
cons = new CtConstructor(new CtClass[]{pool.get("java.lang.String")}, cc);
// $0=this / $1,$2,$3... 代表方法參數
cons.setBody("{$0.name = $1;}");
cc.addConstructor(cons);
// 6. 創建一個名爲printName方法,無參數,無返回值,輸出name值
CtMethod ctMethod = new CtMethod(CtClass.voidType, "printName", new CtClass[]{}, cc);
ctMethod.setModifiers(Modifier.PUBLIC);
ctMethod.setBody("{System.out.println(name);}");
cc.addMethod(ctMethod);
//這裏會將這個創建的類對象編譯爲.class文件
cc.writeFile("D:/");
}
public static void main(String[] args) {
try {
demo();
} catch (Exception e) {
e.printStackTrace();
}
}
}
好了, 基本的使用. 我也是參照這個寫的入門的例子, 就到這裏了
如果覺得不夠的話, 可以去參考這個, 寫的很詳細, 我就不繼續寫了.
https://www.cnblogs.com/rickiyang/p/11336268.html
實際的環境是, 我並不需要產生文件到磁盤上去, 再加載到內存中, 我只需要把java代碼的字符串進行編譯, 然後運行得到結果就可以了. 具體的.class文件我並不關心.