Nam*_*man 6 java lambda jvm startup java-9
通过java.lang.module我在类文档中阅读以下内容:
Run Code Online (Sandbox Code Playgroud)@implNote ... is used at VM startup and so deliberately avoids using lambda and stream usages in code paths used during startup.
使用lambda和流的原因是什么,以及它们可能产生的影响是什么?
插图有助于更好地理解,而不是在这里寻找意见.
apa*_*gin 10
不依赖于lambda和流(广泛使用lambdas)有助于避免在VM引导程序中执行冗余工作.这反过来又减少了启动时间和内存占用.
invokedynamicJDK中的机器相当复杂.它涉及许多java.lang.invoke.*与方法句柄,Lambda Metafactories等相关的类,需要加载和初始化.此外,链接invokedynamic字节码JVM使用ObjectWeb ASM框架动态创建适配器.在运行时生成这样的类也需要时间和空间.
让我们衡量在一个非常基本的场景中使用lambda而不是内部类的开销.我创建两个类似的类,除了实例化内部类或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();
}
}
Run Code Online (Sandbox Code Playgroud)
然后我打开两个类加载日志:
java -Xlog:class+load:file=inner.log Inner
java -Xlog:class+load:file=lambda.log Lambda
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
完整输出在这里.我们可以看到,Inner需要136 ms和537个加载类,同时Lambda需要161 ms和620个加载类.
因此,在这个简单的例子中,避免单个lambda有助于节省25毫秒的启动时间,减少了83个类的加载.
编辑
我所描述的开销包括两部分:
java.lang.invoke.*类 - 这是需要仅执行一次的常量部分.| 归档时间: |
|
| 查看次数: |
162 次 |
| 最近记录: |