运行于JVM上的JavaScript
既然JVM上面可以运行客体语言, 那么会不会有人在JVM上运行JavaScript? 还别说, 真有!
ringo.js
先说第一个项目,ringo,它在github上有600多的star数目.
解压缩放入path后运行ringo, 进入其REPL, 我试了一下, 下面的是可以运行的:
f = function(s){console.log(s)}
f('hello')
ringo有自己的包管理工具rp, 跟npm差不多. 不过需要安装:
ringo-admin install grob/rp
然而我在windows 10上安装却会报错:
Wrapped java.lang.UnsupportedOperationException
at fs.js:1100 (changePermissions)
at C:\l\tools\admin\install.js:86 (installPackage)
at C:\l\tools\admin\install.js:156 (main)
at C:\l\tools\admin\main.js:14 (main)
at C:\l\tools\admin\main.js:30
哦...这就无法继续了...
一个语言的强大在于其库的强大,如果它能同时使用npm和java库,那就真的非常强大了,看来暂时是无法验证了.
java8 jjs: oracle nashorn
没错. Java8支持JavaScript, 这个运行工具就是jjs, 正式名字叫做Nashorn. Oracle官方的这篇文章 Oracle Nashorn: A Next-Generation JavaScript Engine for the JVM有一些说明, 我查了一下我的java, 还真是8:
λ java -version
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
根据文章说, jjs和java在同一目录, 能运行java就意味着jjs也能运行, 先看看版本:
λ jjs -v
nashorn 1.8.0_111
jjs>
果然进来了呢! 试了一下, 居然不支持console.log
...
对应的打印命令,居然是print
...
对此, 文章是这样解释的: 虽然我们兼容ECMA, 但是浏览器环境下的特有变量我们是不支持的,比如window, console这些.
好处呢? 一个是在Java中调用JavaScript代码,还能用到JavaScript的库, 恩,这个感觉比较符合oracle的思路...
文中举例了在Java中调用mustache.js库的方式.
package sample2;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.FileReader;
public class Mustache {
public static void main(String... args) throws Throwable {
ScriptEngineManager engineManager =
new ScriptEngineManager();
ScriptEngine engine =
engineManager.getEngineByName("nashorn");
engine.eval(new FileReader("src/sample2/mustache.js"));
Invocable invocable = (Invocable) engine;
String template = "Email addresses of {{contact.name}}:\n" +
"{{#contact.emails}}\n" +
"- {{.}}\n" +
"{{/contact.emails}}";
String contactJson = "{" +
"\"contact\": {" +
"\"name\": \"Mr A\", \"emails\": [" +
"\"contact@some.tld\", \"sales@some.tld\"" +
"]}}";
Object json = engine.eval("JSON");
Object data =
invocable.invokeMethod(json, "parse", contactJson);
Object mustache = engine.eval("Mustache");
System.out.println(invocable.invokeMethod(
mustache, "render", template, data));
}
}
另一个是在JavaScript中调用Java,这个我比较关心. 哦, 直接调用就好了, 很简单的样子:
print(java.lang.System.currentTimeMillis());
Java对象也可以使用new
来实体化, 这个就酷了:
var file =
new java.io.File("sample.js");
print(file.getAbsolutePath());
print(file.absolutePath);
java.io.File
虽然没有定义absolutePath
,但是定义了getAbsolutePath()
, jjs会自动增加absolutePath
这个属性. 对set也是一样.
这样来看,nashorn很可能可以同时使用部分npm库和java库,看上去很强大的样子.
剩下一个问题就是速度了. nashorn和v8对比速度如何? 从这篇文章来说,还是要差一些的. 对ES的支持呢? 似乎是支持到ES5.1,还没有对新特性的支持. 试了一下ES6中的箭头函数, 果然是没有支持的. 这点上就远不如node.js那么积极啦.
jjs> var a = ()=>{print()}
ECMAScript Exception: SyntaxError: <shell>:1:9 Expected an operand but found )
var a = ()=>{print()}
^
rhino.js
哦, 这个就是被java8抛弃的那个, mozilla基金会的项目, 官网, github项目地址