Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8232806

Introduce a system property to disable eager lambda initialization





        Lambdas generated by `LambdaMetaFactory` are eagerly and unconditionally initialized with `Unsafe` right after class loading. This interferes with heap-snapshotting tools such as GraalVM Native Image: When a lambda is initialized during parsing, all of the super-interfaces with default methods will be initialized too. Static initializers of those interfaces pollute the heap snapshot and lead to unexpected behavior.

        We would like to introduce a flag `jdk.internal.lambda.eagerlyInitialize`, which is `true` by default, and that can be used to prevent the eager initialization of lambdas. The proposed solution is summarised in the two following commits:

         1) Introduces a new shape of non-capturing lambdas, where the lambda instance is kept in a static field:

         2) Introduces the conditional initialization of lambdas as a pure performance optimization:


        With the proposed scheme we get simpler code, that can be used for heap snapshotting and 1.5% better startup time for `HelloLambda.java`. The detailed numbers follow.

        For all the tests we used the same configuration: `Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz` bound to a single socket with turbo disabled. We measured the Java 11 master (master), Java 11 with the first patch (patched) and Java 11 with the patch and lambdas pre-initialized with Unsafe (patched-init). For the instructions count, we used `perf stat` and executed 3 times a 100 runs and took the average. The standard deviation is very small for the interpreter case so I don’t report it. Here are the results:

         (1) I measured only the number of instructions due to the OS noise related to time. The "Hello, Lambda!" numbers are with the JIT enabled.
              | Branch | Instructions |
              | master | 500,490,396 |
              | patched | 492,933,691 |
              | patched-init | 483,938,234 |

          (2) The instruction count is measured in the interpreter (-Xint) and JIT and the time is measured only with the JIT enabled:
              | Branch | Instructions (-Xint) | Instructions (JIT) | Time in us (JIT)|
              | master | 1,285,945,379 | 1,922,974,572 | 227,837 |
              | patched | 1,315,914,375 | 2,058,175,796 | 233,457 |
              | patched-init | 1,286,079,726 | 1,986,969,597 | 218,579 |


            Issue Links



                vjovanovic Vojin Jovanovic
                vjovanovic Vojin Jovanovic
                0 Vote for this issue
                16 Start watching this issue