我最近开始学习nashorn。我很惊讶地发现我们现在可以从 Java 代码中运行 javascript。我想知道如果我们使用 javascript 而不是整个 java 代码,它实际上会提高系统的性能吗?调用js不会做上下文切换再返回吗?
我的问题的另一部分: 我尝试创建一个测试项目,并且能够从java代码运行js。
public class JSFromJava {
static class JavaClass {
int intValue;
String data;
long longValue;
public int getIntValue() {
return intValue;
}
public void setIntValue(int intValue) {
this.intValue = intValue;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public long getLongValue() {
return longValue;
}
public void setLongValue(long longValue) {
this.longValue = longValue;
}
@Override
public String toString() {
return "JavaClass [intValue=" + intValue + ", data=" + data
+ ", longValue=" + longValue + "]";
}
}
public static void main(String[] args) throws ScriptException, IOException, NoSuchMethodException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
// read script file
engine.eval(Files.newBufferedReader(Paths.get("e:/js/a.js"), StandardCharsets.UTF_8));
Invocable inv = (Invocable) engine;
// call function from script file
Object op = inv.invokeFunction("incrementValueByTen", 2);
System.out.println(op);
JavaClass jc = new JavaClass();
jc.intValue=2;
jc.longValue=56;
jc.data="data";
System.out.println(jc);
inv.invokeFunction("updateJavaObject", jc);
System.out.println(jc);
}
}
Javascript 文件:
function incrementValueByTen(arg) {
return arg + 10;
}
function updateJavaObject(arg) {
print("arg recieved::::"+arg)
print(arg.getIntValue())
arg.setIntValue(5);
arg.data=incrementValueByTen(arg.data);
arg.longValue=incrementValueByTen(arg.longValue);
print("arg updated::::"+arg)
}
正如我们所看到的,我正在尝试更新 java 对象或使用传递给第二个函数的 java 对象。我收到问题说 arg 没有这些方法。所有属性也都为空。
第一个方法工作完美,因为它使用原始类型。
这是否意味着我们不能将 java 对象作为参数传递给任何方法?
请提出建议。
谢谢 阿米特
最佳答案
这里的问题是 JavaClass
不是公共(public)的;如果 Java 类不是公共(public)的,那么它的方法实际上也不是公共(public)的,即使您将它们声明为“公共(public)”,除非它们重写父类(super class)方法或实现该类实现的接口(interface)方法。这不是 Nashorn 特有的问题,通常来说,您不能在非公共(public)类上调用公共(public)方法,除非它们是在公共(public)父类(super class)或实现的接口(interface)上声明的。如果将其更改为 public static class JavaClass
,您应该能够从 JS 调用其方法。
至于“从 JS 到 Java 的上下文切换”;没有这样的事。 Nashorn 将 JS 程序编译为 Java 字节码类,并使用 INVOKEDYNAMIC 指令从 JS 调用 Java 方法; HotSpot 通常与 INVOKEVIRTUAL 一样有效地链接它(这是编译后的 Java 代码调用该方法的方法),但需要注意的是,在 JS 中它实际上看起来完全不同。例如。而在 Java 中它看起来像:
ALOAD 1
INVOKEVIRTUAL "int JavaClass.getIntValue()"
在 Nashorn,它实际上是
ALOAD 1
INVOKEDYNAMIC "dyn:getMethod:getIntValue"
ALOAD 1
INVOKEDYNAMIC "dyn:call"
(因此,有两个 INVOKEDYNAMIC:一个用于检索类上的方法,另一个用于调用它;在 JS 中,所有方法调用都是这样的两步)。
您还可以使用属性 getter 语法:
print(arg.intValue)
在这种情况下,arg.intValue
被编译为
ALOAD 1
INVOKEDYNAMIC "dyn:getProp:intValue"
链接器机制知道将其转换为对对象的 getIntValue()
调用。因此,如果可以的话,属性 getter 语法实际上最终会编译为更小的字节码(请注意,这不一定更快,但很有可能是这样)。
关于java - 如何使用纳肖恩?它如何提高性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28470828/