javassist使用解析

當時接到一個活, 需要做程序的評測, 前端傳遞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文件我並不關心.

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章