簡體   English   中英

如何使用Nashorn? 如何提高性能?

[英]How to use Nashorn? How it improve performance?

我最近開始學習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不是公共的。 如果Java類不是公共的,則即使您將它們聲明為“公共”,其方法實際上也不是公共的,除非它們重寫了超類方法或實現了該類實現的接口方法。 這不是Nashorn特有的問題,通常是可以的,除非在公共超類或已實現的接口上聲明了公共方法,否則您不能在非公共類上調用公共方法。 如果將其更改為public static class JavaClass ,則應該能夠從JS調用其方法。

至於“上下文從JS切換到Java並返回”; 沒有這樣的事情。 Nashorn將JS程序編譯為Java字節碼類,並使用INVOKEDYNAMIC指令從JS調用Java方法。 HotSpot通常將其鏈接起來與INVOKEVIRTUAL一樣有效(這是已編譯的Java代碼將調用該方法進行的操作),但需要注意的是,在JS中,它實際上看起來完全不同。 例如,在Java中,它看起來像:

ALOAD 1
INVOKEVIRTUAL "int JavaClass.getIntValue()"

在納斯霍恩,實際上是

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語法實際上最終會編譯為較小的字節碼(請注意,這不一定會更快,但這是個不錯的選擇)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM