Java内存代码的动态编译(运行时编译)

发表于2019-12-18,长度1215, 210个单词, 3分钟读完
Flag Counter

Java 可以在运行时动态编译并执行代码,一种代码是本来就可以在虚拟机上跑的字节码,如Java、Scala、groovy等,另一类是Java特意提供了执行引擎的JavaScript。这里看一下如何进行动态编译。

JS引擎

据说Java以后会删掉JS引擎,所以最好不要依赖

这个很简单:

String original = "var res = 0.0; if (#1 >= 1000) { res = #1 * 0.1 ;} else if (#1 >= 100) {res = #1 * 0.01} ; res ;";
String script = original.replace("#1", "100");
try {
     ScriptEngine engine = new ScriptEngineManager().getEngineByName("Nashorn");
    log.info("结果 {}", engine.eval(script));
} catch (ScriptException e) {
    e.printStackTrace();
}

历史上,Java提供过几个JS引擎的实现,现在Nashorn是性能最好、JS特性支持最广泛的一个。

Groovy 引擎

groovy的执行方式比较多样,这里不说了,放一篇链接:《柚子工具 - Groovy&Java动态编译执行》。里面介绍了groovy执行的两种方式,你可以到百度上谷歌一下,还有更多其他方法。后面也提到,动态脚本的效率没法和Java比,而Java也支持动态编译。所以我们这里说一下Java的编译。

Java 动态编译

上面那篇外部引用讲了如何进行动态编译,这里就不重复讲解了。不过我想给大家介绍一个工具,能够方便的进行内存中代码的动态编译:

<dependency>
    <groupId>org.jooq</groupId>
    <artifactId>joor-java-8</artifactId>
    <version>0.9.8</version>
</dependency>

通过以上依赖,我们可以这样编写代码:

String s = "import java.math.BigDecimal;class A{BigDecimal a(){return new BigDecimal(\"#1\").multiply(new BigDecimal(\"0.12\"));}}";
String script = s.replace("#1", "100");
log.info("结果 {}", Reflect.compile("A", script).create().call("a"));

后面的call写入方法名称即可。

Written on December 18, 2019
分类: dev, 标签: java asm
如果你喜欢,请赞赏! davelet