01 引言
Janino
是一个开源的轻量级Java
编译器,它可以执行Java
代码片段、类、方法等,而无需通过javac
编译。这个框架的好处是,可以调用API去动态编译并执行传入的java字符串,且整个编译过程可以做到无感知。
02 Janino的基本使用
需求:现在期望通过输入一个类定义的java字符串(内容逻辑为输出Hello World),然后使用Janino去动态编译并执行。
首先,需要在项目中添加Janino
依赖,可以通过Maven
或Gradle
添加,以下是使用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
即可以实现动态编译并运行了。
其实在很多开源项目中都有Janino
的影子,例如 Flink 中protobuf-format代码中的PbCodegenUtils实现(RowData
与protobuf
二进制字节流的转换):
Janino编译逻辑:
03 文末
Janino
是一款强大而易用的Java
动态编译工具,用途非常广泛:可以用它来编译并执行Java代码片段,也可以用它来动态生成和编译整个Java类。但它也有自己的局限性:不支持Java 8及以上特性,如stream和lambda,也不能直接操作字节码。因此,对于需要复杂逻辑或操作字节码的任务,你可能需要查看其他动态编译工具(例如:ASM
, Javassist
, CGLIB
等)。在选择使用Janino
之前,需要确保它可以满足已有的应用场景和需求。
谢谢大家的阅读,希望能帮助到大家,本文完!