Consider the following class:
final class CapturingLambda {
Runnable withAnonymousRunnableInside() {
return () -> {
Runnable r = new Runnable() {
@Override
public void run() {
}
};
r.run();
};
}
Runnable withLocalClassInside() {
return () -> {
class Local {}
new Local();
};
}
}
The lambdas here are not using the instance of an outer CapturingLambda object, so I expect that they should not capture it. However, this is not the case. Lambda synthetic methods are non-static, and CapturingLambda this object is passed to invokedynamic:
0: aload_0
1: invokedynamic #7, 0 // InvokeDynamic #0:run:(LCapturingLambda;)Ljava/lang/Runnable;
This prevents from creating a singleton lambda instance and unnecessarily keeps the strong reference to an outer object. I think this could be fixed.
discussed in compiler-dev: https://mail.openjdk.org/pipermail/compiler-dev/2025-November/032133.html
final class CapturingLambda {
Runnable withAnonymousRunnableInside() {
return () -> {
Runnable r = new Runnable() {
@Override
public void run() {
}
};
r.run();
};
}
Runnable withLocalClassInside() {
return () -> {
class Local {}
new Local();
};
}
}
The lambdas here are not using the instance of an outer CapturingLambda object, so I expect that they should not capture it. However, this is not the case. Lambda synthetic methods are non-static, and CapturingLambda this object is passed to invokedynamic:
0: aload_0
1: invokedynamic #7, 0 // InvokeDynamic #0:run:(LCapturingLambda;)Ljava/lang/Runnable;
This prevents from creating a singleton lambda instance and unnecessarily keeps the strong reference to an outer object. I think this could be fixed.
discussed in compiler-dev: https://mail.openjdk.org/pipermail/compiler-dev/2025-November/032133.html