This change introduces a system property
jdk.internal.lambda.disableEagerInitialization that is false by default. When true, the new flag is used to prevent eager initialization of lambda proxy classes (generated by LambdaMetaFactory) during the lambda class generation, and disables the optimization to cache non-capturing lambdas at the call site.
This change is motivated by the desire to minimize class initialization when performing heap snapshots, such as via GraalVM Native Image. Lambdas are initialized during image generation; eager initialization of lambdas causes the static initializers of lambda super-interfaces to be run, which is earlier than may be desired when performing heap snapshots. By delaying lambda initialization to runtime, lambda static initialization is performed lazily, resulting in the appropriate phase (build time or run time) according to the user specification.
By default, LambdaMetafactory links lambda factory sites to the constructor for the lambda proxy class for capturing lambdas, but eagerly evaluates an instance of the lambda for non-capturing lambdas, and links the callsite to always return that instance. When eager initialization is disabled with
-Djdk.internal.lambda.disableEagerInitialization=true then the latter optimization, where the instance is eagerly evaluated and cached, is disabled, and the initialization of the lambda proxy class is performed lazily (when the callsite is invoked) rather than eagerly with
Unsafe.ensureClassInitialized (when the callsite is linked.)
Multiple solutions have been prototyped; this solution was chosen because it was minimally disruptive.
If the system property
jdk.internal.lambda.disableEagerInitialization has the value
"true" (ignoring case) then instances of non-capturing lambdas are not eagerly evaluated. If this system property has any other value, or has no value, then such lambdas are eagerly evaluated, as they have been since JDK 8.