0
点赞
收藏
分享

微信扫一扫

一文理解Janino:动态编译Java代码的神器


01 引言

Janino是一个开源的轻量级Java编译器,它可以执行Java代码片段、类、方法等,而无需通过javac编译。这个框架的好处是,可以调用API去动态编译并执行传入的java字符串,且整个编译过程可以做到无感知。

  • 源码地址:https://github.com/janino-compiler/janino
  • 首页:https://janino-compiler.github.io/janino/

02 Janino的基本使用

需求:现在期望通过输入一个类定义的java字符串(内容逻辑为输出Hello World),然后使用Janino去动态编译并执行。

首先,需要在项目中添加Janino依赖,可以通过MavenGradle添加,以下是使用maven的方式添加:

<dependency>
  <groupId>org.codehaus.janino</groupId>
  <artifactId>janino</artifactId>
  <version>3.1.6</version>
</dependency>

接着可以写janino相关的代码,内容如下:

/**
 * Janino演示
 *
 * @author : YangLinWei
 * @createTime: 2024/1/22 18:50
 * @version: 1.0.0
 */
public class JaninoTest {

    public static void main(String[] args) throws Exception {
        // 类定义
        String classDef = "public class HelloWorld { public static void helloWorld() { System.out.println(\"Hello, world!\"); } }";

        // 使用janino动态编译字符串并加载进类加载器
        SimpleCompiler sc = new SimpleCompiler();
        sc.cook(classDef);
        Class<?> clazz = sc.getClassLoader().loadClass("HelloWorld");

        // 使用janino执行
        clazz.getMethod("helloWorld").invoke(null);
    }
}

运行:

一文理解Janino:动态编译Java代码的神器_动态编译

可以看到,我们通过动态传入类定义的字符串,使用Janino即可以实现动态编译并运行了。

其实在很多开源项目中都有Janino的影子,例如 Flink 中protobuf-format代码中的PbCodegenUtils实现(RowDataprotobuf二进制字节流的转换):

一文理解Janino:动态编译Java代码的神器_动态编译_02

Janino编译逻辑:

一文理解Janino:动态编译Java代码的神器_类定义_03

03 文末

Janino是一款强大而易用的Java动态编译工具,用途非常广泛:可以用它来编译并执行Java代码片段,也可以用它来动态生成和编译整个Java类。但它也有自己的局限性:不支持Java 8及以上特性,如stream和lambda,也不能直接操作字节码。因此,对于需要复杂逻辑或操作字节码的任务,你可能需要查看其他动态编译工具(例如:ASM Javassist CGLIB等)。在选择使用Janino之前,需要确保它可以满足已有的应用场景和需求。

谢谢大家的阅读,希望能帮助到大家,本文完!


举报

相关推荐

0 条评论