K 的博客

记录精彩的程序人生 开始使用

java 脚本引擎

JS 引擎

自从 Java1.6 以后 Java 就自带 js 引擎,这个支持来自于 JSR223 规范,对应的包是 javax.script。1.6、1.7 使用 Rhino 引擎,1.8 使用 Nashorn 引擎。
Rhino 和 Nashorn 都是用 Java 实现的 JavaScript 引擎。它们自身都是普通的 Java 程序,运行在 JVM 上。

JS 的 Rhino 引擎

Rhino 引擎有 解释和编译 两种执行模式, 1.6 只支持解释执行模式,1.7 默认也是解释执行,可以通过设置 Rhino 的优化级别(optimization level)来改变。
当优化级别为-1 时,Rhino 使用一个用 Java 写的字节码解释器来解释执行 JavaScript。

此时,Rhino 的工作流程简单说是:( [ ... ]表示数据实体,( ... )表示 Rhino 处理数据的程序)
[ JavaScript 源码 ] -> ( 语法分析器 Parser ) -> [ 抽象语法树(AST) ast ] -> ( Rhino 内部表现形式生成器 IRFactory ) -> [ Rhino 内部表现形式 ScriptNode ] -> ( Rhino 字节码生成器 CodeGenerator ) -> [ Rhino 字节码 Icode ] -> ( Rhino 解释器 Interpreter ) -> [ 运行结果 ]
这里说的 Rhino 字节码是 Rhino 内部用来表示 JavaScript 程序语义的一套字节码,跟 JVM 所支持的 Java 字节码没关系。
当优化级别为 0~9 时,Rhino 使用一个用 Java 写的编译器将 JavaScript 编译为 Java 字节码;生成出来的 Java 字节码交由 JVM 直接执行。至于底下的 JVM 是解释执行 Java 字节码,还是将 Java 字节码编译为机器码再执行,Rhino 并不关心。

此时,Rhino 的工作流程简单说是:
[ JavaScript 源码 ] -> ( 语法分析器 Parser ) -> [ 抽象语法树(AST) ast ] -> ( Rhino 内部表现形式生成器 IRFactory ) -> [ Rhino 内部表现形式 ScriptNode ] -> ( 可选优化 Optimizer ) -> ( Java 字节码生成器 Codegen ) -> [ Java Class 文件(包含 Java 字节码) ] -> JVM 加载和执行生成的字节码 -> [ 运行结果 ]

这种以编译的方式模式执行 JavaScript,跟一个 Java 源码编译器(例如 javac)把 Java 源码编译为 Class 文件然后交由 JVM 执行,过程是类似的。只不过 Rhino 做的优化不够多而且 JavaScript 的语义也远比 Java 动态,所以此时 Rhino 上运行 JavaScript 的性能仍然无法跟 Java 的性能比。

JS 的 Nashorn 引擎

Nashorn 引擎:是一个纯编译的 JavaScript 引擎。它没有用 Java 实现的 JavaScript 解释器,而只有把 JavaScript 编译为 Java 字节码再交由 JVM 执行这一种流程,跟 Rhino 的编译流程类似。

[ JavaScript 源码 ] -> ( 语法分析器 Parser ) -> [ 抽象语法树(AST) ir ] -> ( 编译优化 Compiler ) -> [ 优化后的 AST + Java Class 文件(包含 Java 字节码) ] -> JVM 加载和执行生成的字节码 -> [ 运行结果 ]

中间这个“编译优化”通过 CompilationPhase 来组织。最基本的工作流程可以从 Compiler.CompilationPhases.COMPILE_ALL 来看。

Java 1.6 JS 支持

它底层的实现是 Mozilla Rhino,它是个纯 Java 的 JavaScript 实现。
自带的 Rhino 是经过裁剪的,去掉了 Mozilla Rhino 中的部分功能。其中一个被去掉的功能就是 Rhino 的编译模式。这意味着 JDK6 自带的 Rhino 只能用解释模式运行。

在 java1.6 中使用 Mozilla Rhino 引擎,💢 应该是简化版的实现 💢,只支持脚本的解释执行,性能方面低于 Java。

Java 1.7 JS 支持

与 1.6 一样都是 Rhino 引擎默认应该都是 解释执行,但是 1.7 好像可以通过配置系统属性实现 编译运行 从而提升性能。

当优化级别为-1 时,Rhino 使用一个用 Java 写的字节码解释器来解释执行 JavaScript。当优化级别为 0~9 时,Rhino 使用一个用 Java 写的编译器将 JavaScript 编译为 Java 字节码;生成出来的 Java 字节码交由 JVM 直接执行。

设置优化级别 :System.getProperties().setProperty("rhino.opt.level", "1");
官方说明文档
使用文档

Java 1.8 JS 支持

与 1.6、1.7 不一样引擎升级为 Nashorn ,直接编译执行。
Nashorn 是一个纯编译的 JavaScript 引擎。它没有用 Java 实现的 JavaScript 解释器,而只有把 JavaScript 编译为 Java 字节码再交由 JVM 执行这一种流程,跟 Rhino 的编译流程类似。
注:应该在编译的时候会比较消耗 CPU,编译完成后性能非常接近 Java 原生,所以最好把一段 js 代码编译生成的对象静态化一下,当 js 代码更新后在重新生成 新的对象。

Groovy 引擎

Groovy

Jython(Python)引擎

Jython

Jruby(Ruby)引擎

Jruby

kotlin 引擎

kotlin

评论
留下你的脚步