java - 如何使用纳肖恩?它如何提高性能?

标签 java javascript

我最近开始学习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/

相关文章:

java - Spring @PageableDefault 默认方向在传递排序后发生变化

javascript - 模块中的 NodeJS 所需模块始终未定义

javascript - GreenSock 和 TypeScript

Javascript 表单输入值更新仅在调试条件下成功

java - Realm 中的 allObjects() 方法是否已弃用?

java - 在二维数组中查找字符串,然后转到相应的列

Java ScheduledExecutorService 以 100% 运行一个 CPU 核心(但不执行任务)

javascript - 为什么在 webkit 中没有触发 'beforepaste' 事件?

javascript - 如何在没有其子项的 innerText 的情况下在 JavaScript 中获取 h1 innerText?

java - 动态创建文本字段