0%

JaninoCompiler

JaninoCompiler

http://janino-compiler.github.io/janino/

Janino is a super-small, super-fast Java™ compiler.

极小、极快、开源,不依赖JDK(只依赖JRE,free)的动态编译器

从内存获取classes文件,不依赖IO

类似的工具:

  • Jasper: 需要依赖JDK
  • Eclipse compiler

使用场景

  1. 类似Javac,Java源文件文件编译成字节码文件

  2. 编译Java表达式、块、类和源码文件

  3. 静态代码分析和代码操作

  4. 性能优化

    1. 动态编译类取代Java代理类,避免所有的反射,显著提高性能。
    2. Codegen
  5. 规则引擎: 取代DSL(预定义语言: Domain-Specific Language)

  6. Codegen

Janino应用

  1. Kettle: ETL工具 [Kettle-JavaNode]
  2. slf4j + log4j/logback [[JaninoEventEvaluator]]
  3. Apache Commons JCL
  4. JBoss Rules/Drools
  5. Flink SQL
  6. Spark SQL

问题:

  1. 能否动态卸载?

使用教程

1
2
3
4
5
<dependency>  
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.1.6</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 首先定义一个表达式模拟器ExpressionEvaluator对象
ExpressionEvaluator ee = new ExpressionEvaluator();

// 定义一个算术表达式,表达式中需要有2个int类型的参数a和b
String expression = "2 * (a + b)";
ee.setParameters(new String[] { "a", "b" }, new Class[] { int.class, int.class });

// 设置表达式的返回结果也为int类型
ee.setExpressionType(int.class);

// 这里处理(扫描,解析,编译和加载)上面定义的算数表达式.
ee.cook(expression);

// 根据输入的a和b参数执行实际的表达式计算过程
int result = (Integer) ee.evaluate(new Object[] { 19, 23 });
System.out.println(expression + " = " + result);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ScriptEvaluator se = new ScriptEvaluator();
se.setParameters(new String[] { "arg1", "arg2" }, new Class[] { String.class, int.class });
se.cook(
"System.out.println(arg1);\n"
+ "System.out.println(arg2);\n"
+ "\n"
+ "static void method1() {\n"
+ " System.out.println(\"run in method1()\");\n"
+ "}\n"
+ "\n"
+ "public static void method2() {\n"
+ " System.out.println(\"run in method2()\");\n"
+ "}\n"
+ "\n"
+ "method1();\n"
+ "method2();\n"
);
se.evaluate(new Object[]{"aaa",22});
1
2
3
4
5
6
7
8
9
10
11
12
13
public interface Foo {
int bar(int a, int b);
}

public static void main(String[] args) throws Exception {
Foo f = (Foo) ClassBodyEvaluator.createFastClassBodyEvaluator(
new Scanner(null, new StringReader("public int bar(int a, int b) { return a + b; }")),
Foo.class, // 实现的父类或接口
(ClassLoader) null // 这里设置为null表示使用当前线程的class loader
);
System.out.println("1 + 2 = " + f.bar(1, 2));

}