如果你只要 Java7 及以下的语法支持,建议 Janino。如果要你想更全的 Java8、Java11、Java17、Java21 等语法,可以选 Liquor。
1、它们相同的地方
接口 | Janino | Liquor |
---|
动态编译器 | SimpleCompiler | DynamicCompiler |
表达式评估器 | ExpressionEvaluator | LiquorEvaluator (Exprs) |
脚本评估器 | ScriptEvaluator | LiquorEvaluator (Scripts) |
- 都是 Java 语言(语法)的动态应用。生成的字节码都可以完全访问 JRE,可能要注意安全的控制。
2、细节区别处
- Janino 基于自已的编译能力实现。
- 支持 Java7 及以下语法。
- 单次编译性能,更好。
- 支持命令行编译。
- 提供更丰富的功能。比如代码分析器,等。
- Liquor 基于 JDK 自带的编译能力实现。
- 支持 Java8、Java11、Java17、Java21 等语法(由运行时版本决定)。
- 单次编译性能,差些。
- 不支持命令行编译。可用 javac 命令。
3、具体差异 - 动态编译器
动态编译器的性能,基本上可以按“次”计量。次数越多,费时越多。尽量把可知代码,合在一起编译(次数,越少越好)。
public class JaninoTest {
public static void main(String[] args) throws Exception {
SimpleCompiler compiler = new SimpleCompiler();
String className = "HelloWorld";
String classCode = "public class HelloWorld { " +
" public static void helloWorld() { " +
" System.out.println(\"Hello, world!\"); " +
" } " +
"}";
compiler.cook(classCode);
Class<?> clazz = compiler.getClassLoader().loadClass(className);
clazz.getMethod("helloWorld").invoke(null);
}
}
public class LiquorTest {
public static void main(String[] args) throws Exception{
DynamicCompiler compiler = new DynamicCompiler();
String className = "HelloWorld";
String classCode = "public class HelloWorld { " +
" public static void helloWorld() { " +
" System.out.println(\"Hello, world!\"); " +
" } " +
"}";
compiler.addSource(className, classCode);
compiler.build();
Class<?> clazz = compiler.getClassLoader().loadClass(className);
clazz.getMethod("helloWorld").invoke(null);
}
}
4、具体差异 - 表达式评估器
比较 | Janino | Liquor |
---|
缓存 | 无(可以自己包装) | 有二级缓存(类加载器缓存,编译结果缓存) |
体验 | 每次要重新构建 | 方便 |
性能 | 单次更好 | 缓存命中时,非常好(接近原始 Java 代码性能) |
public class JaninoTest {
public static void main(String[] args) throws Exception {
ExpressionEvaluator ee = new ExpressionEvaluator();
ee.cook("3 + 4");
System.out.println(ee.evaluate());
}
}
public class LiquorTest {
public static void main(String[] args) throws Exception {
System.out.println(Exprs.eval("3 + 4"));
}
}
5、具体差异 - 脚本评估器
比较 | Janino | Liquor |
---|
缓存 | 无(可以自己包装) | 有二级缓存(类加载器缓存,编译结果缓存) |
体验 | 每次要重新构建 | 方便 |
性能 | 单次更好 | 缓存命中时,非常好(接近原始 Java 代码性能) |
public class JaninoTest {
public static void main(String[] args) throws Exception {
ScriptEvaluator se = new ScriptEvaluator();
se.cook("System.out.println(\"hello word\");");
se.evaluate();
}
}
public class LiquorTest {
public static void main(String[] args) throws Exception {
Scripts.eval("System.out.println(\"hello word\");");
}
}