[code-reflection] RFR: Lazily invoke lambda op building method
Paul Sandoz
psandoz at openjdk.org
Fri Dec 19 21:04:07 UTC 2025
On Fri, 19 Dec 2025 16:02:42 GMT, Mourad Abbay <mabbay at openjdk.org> wrote:
> Validation introduced in #738 is causing reflectable lambda creation to fail with an `InternalError`. The reason for this is that we are invoking lambda op building method in the lambda class static initializer, when lambda op building method throws UOE, it causes lambda creation to fail with `InternalError`. What we want is `Op.ofQuotable` to fail but not lambda instantiation. To adress this, we now lazily invoke lambda op building method and as result we lazily compute the `Quoted` instance, while sharing the lambda model across instances of the same lambda class.
src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java line 497:
> 495:
> 496: /**
> 497: * Generate method #__internal_quoted()
Inside the method can you document the representative Java code for "getQuoted" and "getModel"?
src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java line 518:
> 516: .getfield(lambdaClassEntry.asSymbol(), QUOTED_FIELD_NAME, reflectableLambdaInfo.quotedClass())
> 517: .ifnonnull(nonNull)
> 518: .aload(0);// will be used by putfield to store the quoted instance
See if using `cob.ifThen` makes the code clearer.
src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java line 548:
> 546: .aload(0)
> 547: .getfield(lambdaClassEntry.asSymbol(), QUOTED_FIELD_NAME, reflectableLambdaInfo.quotedClass())
> 548: .areturn();
You are loading the field twice. It seems clearer to use a local variable as in:
T v = a;
if (v == null) {
v = a = ...;
}
return v;
src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java line 553:
> 551:
> 552: clb.withMethod("getModel", MethodTypeDesc.of(reflectableLambdaInfo.funcOpClass()),
> 553: ACC_PRIVATE + ACC_STATIC + ACC_SYNCHRONIZED,
This method does not need to be synchronized since it is only called by `getQuoted` which is synchronized.
src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java line 558:
> 556: public void accept(CodeBuilder cob) {
> 557: Label nonNull = cob.newLabel();
> 558: cob.getstatic(lambdaClassEntry.asSymbol(), MODEL_FIELD_NAME, reflectableLambdaInfo.funcOpClass())
Similar comment as above regarding loading the field twice.
test/jdk/java/lang/reflect/code/TestLambdaModelUnique.java line 22:
> 20: * @run junit TestLambdaModelUnique
> 21: */
> 22: public class TestLambdaModelUnique {
Maybe rename to `TestOpOfQuotable`?
test/jdk/java/lang/reflect/code/TestMethodModelUnique.java line 17:
> 15: * @run junit TestMethodModelUnique
> 16: */
> 17: public class TestMethodModelUnique {
Maybe rename to `TestOpOfMethod`?
test/jdk/java/lang/reflect/code/TestQuotedUnique.java line 17:
> 15: * @run junit TestQuotedUnique
> 16: */
> 17: public class TestQuotedUnique {
Can we merge with `TestLambdaModelUnique` that is renamed? as it is not clear it is doing anything different.
test/jdk/java/lang/reflect/code/TestQuotedUnique.java line 32:
> 30: int j = 8;
> 31: IntUnaryOperator q = (@Reflect IntUnaryOperator) i -> i * 2 + j;
> 32: List<Quoted> quotedObjects = IntStream.range(1, 3).parallel().mapToObj(_ -> Op.ofQuotable(q).get()).toList();
We need to think more carefully about this approach. I think we need N threads in proportion to the runtime threads all executing and waiting on a count down latch so all are trigger to call `Op.ofQuotable(q)` at the roughly the same time and all threads should produce the same result, returning exactly the same object or throwing UOE. Then run that process in a loop for say 100 iterations.
-------------
PR Review Comment: https://git.openjdk.org/babylon/pull/769#discussion_r2636223938
PR Review Comment: https://git.openjdk.org/babylon/pull/769#discussion_r2636235926
PR Review Comment: https://git.openjdk.org/babylon/pull/769#discussion_r2636263524
PR Review Comment: https://git.openjdk.org/babylon/pull/769#discussion_r2636241384
PR Review Comment: https://git.openjdk.org/babylon/pull/769#discussion_r2636268132
PR Review Comment: https://git.openjdk.org/babylon/pull/769#discussion_r2636276971
PR Review Comment: https://git.openjdk.org/babylon/pull/769#discussion_r2636276075
PR Review Comment: https://git.openjdk.org/babylon/pull/769#discussion_r2636275280
PR Review Comment: https://git.openjdk.org/babylon/pull/769#discussion_r2636292470
More information about the babylon-dev
mailing list