【问题标题】:Does Nashorn Javascript compile "eval" statements?Nashorn Javascript 是否编译“eval”语句?
【发布时间】:2016-11-21 17:15:19
【问题描述】:

我了解 Nashorn 可以即时编译为 JVM 字节码。但是,当 Nashorn 遇到带有 String 的 eval 函数时会怎么做呢?它是编译字符串内容还是解释它?

例如:

function sayHi() {
  console.log("hi world");
}

for (var i=0;i<10;i++) {
   eval("sayHi()"); // what happens here?
}

几个选项可能是: 1) 它不会在 eval 中编译字符串 2)它编译一次,缓存它,然后如果遇到相同的字符串则重用相同的字节码(如上面的循环) 3) 它每次都重新编译一个 eval String 的内容

当然这是一个小例子,其中 eval 字符串的内容只是一个方法调用,但想象一下,将更复杂的 JS 代码作为字符串传递给 eval。

【问题讨论】:

  • eval() 与硬编码字符串一起使用没有什么意义 - 通常不建议使用eval(),但如果您打算使用它,则重点通常是将一个动态创建的字符串传递给它,该字符串的值在编译时是未知的。
  • 好的,我们假设要 eval 的字符串是动态的。是不是先即时编译成一个临时类,然后马上把类卸载掉。或者,它只是类似于 Rhino 解释模式的解释?还是其他选择?

标签: javascript jvm jit nashorn


【解决方案1】:

Nashorn 总是将 javascript 编译为字节码以供执行。 JS 没有解释器。是的,如果无法从活动对象访问,则已编译/加载的类将被卸载。

【讨论】:

  • 那么,在上面的例子中,在循环中,每次调用 eval 都会有一个新的重新编译/卸载类,即使 eval 过去遇到过相同的字符串?
  • 不,相同的代码会有缓存命中。即,不会再次重新编译。根据是否有可用的活动缓存,可以避免编译。但是,代码肯定会再次运行。
  • 因此,为了避免在 eval(String) 中重新编译,它会根据 String.equals 检查它是否已经编译了该特定字符串。感谢您的专家帮助。
  • 没错——如果你好奇,相关的Source和Class缓存代码就在这里——>hg.openjdk.java.net/jdk9/dev/nashorn/file/8a875db19be8/src/…&hg.openjdk.java.net/jdk9/dev/nashorn/file/8a875db19be8/src/…
  • ScriptEngine.eval(Reader reader, ScriptContext ctxt) 做类似的事情吗?如果 scriptEngine 评估具有相同文件名的读取器,它是避免 IO 并仅使用缓存,还是执行 IO,加载字符串,然后检查缓存?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-29
  • 2017-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多