In 8232806, a system property was introduce to disable eager initialization of 
the classes generated by the InnerClassLambdaMetafactory 
(`jdk.internal.lambda.disableEagerInitialization`).

However, when `disableEagerInitialization` is true, even for non-capturing 
lambdas, the capturing lambda path that uses a method handle to the constructor 
is taken.
This helps prevent eager initialization but also has the side effect of always 
returning a fresh instance of the lambda for every invocation instead of a 
singleton.
While this is allowed by the specs, this might change the behaviour of some 
(incorrect) programs that assume a singleton is used for non-capturing lambdas.

I propose to keep the effects of the `disableEagerInitialization` related to 
initialization only.

Webrev: https://cr.openjdk.java.net/~gdub/8242451/webrev.0/
Issue: https://bugs.openjdk.java.net/browse/JDK-8242451

The concrete issue we are seeing with changing both aspects at the same time is 
that when disableEagerInitialization for static analysis in GraalVM's 
native-image, some programs start to miss-behave because of assumptions about 
the object identity of lambdas.


Note that `disableEagerInitialization` is still ineffective in the following 
situations:
* when `useImplMethodHandle` is true, i.e., when a MethodHanlde is used to call 
the target because the generated hidden class is missing the necessary access 
rights.
  (the implementation require setting a static field on the generated class 
which causes it to be initialized, Class Data could help in the future in that 
case)
* for non-capturing lambdas when the caller (and generated) class is in the 
`java.lang.invoke` or `sun.invoke.util` package.
  (because `findStaticGetter` will eagerly initialize the holder class if it is 
from those packages, see DirectMethodHandle#shouldBeInitialized)

Those are acceptable rare corner cases.

Thanks,
 Gilles

Reply via email to