javassist使用解析

当时接到一个活, 需要做程序的评测, 前端传递java代码到后端, 后端进行java代码的评测.

包括java代码是否能够编译运行, 结果是否正确, 程序运行的时间, 以及程序运行占用的内存的. 

这个时候我们就需要使用到java的动态编译了. 其实首先想到的就是JavaCompiler 这个类了, 可以自己实现一套代码的编译逻辑,

但是本着尽量做完的原则, 就不自己造轮子了,这里有个选择,

国人, 廖雪峰 他最JavaCompile对了一个简单的封装, 打成了jar包, 可以实现一些比较简单的编译功能. 试了一下还是蛮好用的.

这里就不列举了.

关于java的动态编译, 我们还可以使用asm 或者 javassit, 这次我们的技术选择使用javassit, 因为asm过于复杂, 时间不允许, 暂时也没有业务场景一定要用到asm,就选择了相对简单的javassit了.

下面我们来说下, javassit的简单使用.

首先需要引入jar包:



    org.javassist
    javassist
    3.26.0-GA


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文件我并不关心.

 

 

 

 

 

 

你可能感兴趣的:(Java,Basic)