的一類通過java.lang.module
去避免Lambda和流使用我讀之間的一類文檔以下:在VM啓動
@implNote ... is used at VM startup and so deliberately avoids using lambda and stream usages in code paths used during startup.
什麼是使用拉姆達的原因和流是在這裏可以避免,它們可能產生什麼影響?
插圖將有助於更好地理解,而不是在這裏尋找意見。
的一類通過java.lang.module
去避免Lambda和流使用我讀之間的一類文檔以下:在VM啓動
@implNote ... is used at VM startup and so deliberately avoids using lambda and stream usages in code paths used during startup.
什麼是使用拉姆達的原因和流是在這裏可以避免,它們可能產生什麼影響?
插圖將有助於更好地理解,而不是在這裏尋找意見。
不依賴於lambdas和流(廣泛使用lambda表達式)有助於避免在虛擬機引導時做冗餘工作。這反過來又減少了啓動時間和內存佔用。
invokedynamic
JDK中的機器相當複雜。它涉及許多與方法句柄,Lambda元函數等有關的類,這些類需要加載和初始化。此外,鏈接invokedynamic
字節碼JVM使用ObjectWeb ASM框架動態創建適配器。在運行時生成這樣的類也需要時間和空間。
讓我們測量在非常基本的場景中使用lambda而不是內部類的開銷。我創建了兩個類似的類是做什麼,但無論是實例化一個內部類或λ:
class Inner {
public static void main(String[] args) {
Runnable r = new Runnable() { public void run() {} };
r.run();
}
}
class Lambda {
public static void main(String[] args) {
Runnable r =() -> {};
r.run();
}
}
然後我用的類加載運行日誌同時打開:
java -Xlog:class+load:file=inner.log Inner
java -Xlog:class+load:file=lambda.log Lambda
inner.log
[0.011s][info][class,load] opened: C:\Program Files\Java\jdk-9\lib\modules
[0.022s][info][class,load] java.lang.Object source: jrt:/java.base
[0.022s][info][class,load] java.io.Serializable source: jrt:/java.base
...
[0.136s][info][class,load] Inner$1 source: file:/C:/Andrei/
[0.136s][info][class,load] java.lang.Shutdown source: jrt:/java.base
[0.136s][info][class,load] java.lang.Shutdown$Lock source: jrt:/java.base
lambda.log
[0.011s][info][class,load] opened: C:\Program Files\Java\jdk-9\lib\modules
[0.022s][info][class,load] java.lang.Object source: jrt:/java.base
[0.022s][info][class,load] java.io.Serializable source: jrt:/java.base
...
[0.159s][info][class,load] Lambda$$Lambda$1/1282788025 source: Lambda
[0.159s][info][class,load] java.lang.invoke.InnerClassLambdaMetafactory$1 source: jrt:/java.base
[0.159s][info][class,load] java.lang.invoke.MethodHandleImpl$IntrinsicMethodHandle source: jrt:/java.base
[0.159s][info][class,load] java.lang.invoke.SimpleMethodHandle source: jrt:/java.base
[0.159s][info][class,load] sun.invoke.util.Wrapper$1 source: jrt:/java.base
[0.160s][info][class,load] java.lang.invoke.LambdaForm$MH/100555887 source: java.lang.invoke.LambdaForm
[0.160s][info][class,load] java.lang.invoke.LambdaForm$MH/1983747920 source: java.lang.invoke.LambdaForm
[0.160s][info][class,load] java.lang.Shutdown source: jrt:/java.base
[0.161s][info][class,load] java.lang.Shutdown$Lock source: jrt:/java.base
全部輸出爲here。正如我們所看到的,Inner
需要136毫秒和537加載的類,而Lambda
需要161毫秒和620加載的類。
因此,在這個簡單的例子中,避免使用單個lambda幫助節省25毫秒的啓動時間,並減少83個加載的類。
編輯
我所描述的開銷由兩個部分組成:
java.lang.invoke.*
類 - 這是一個必須做一次恆定的一部分。另外,假設這裏並提出,如果這可能會被添加到答案。 *單個lambda有助於節省25毫秒的啓動時間,並減少了83個加載的類。*但這種增長會呈指數級增長,而不是乘以lambda的數量。我對麼? – nullpointer
@nullpointer我已經更新了答案。開銷與lambda表達式的數量以及加載和初始化其他類所需的常量開銷成正比。 – apangin
你使用的是'jdk9'嗎?我想,它還沒有發佈。對 ? – Ravi
@Ravi是的,我([early access build](http://jdk.java.net/9/))。這個問題與它的發佈沒有關係,而是一個實現。 – nullpointer
但是,如果有什麼東西沒有發佈,那麼怎麼能有人告訴你他們的用法? – Ravi