JDK-8290417 : CDS cannot archive lamda proxy with useImplMethodHandle
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 17,18,19,20
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2022-07-17
  • Updated: 2022-07-29
  • Resolved: 2022-07-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17 JDK 19 JDK 20
17.0.5-oracleFixed 19 b32Fixed 20Fixed
Related Reports
Relates :  
Description
See Test.java from the attachment for the reproduction steps:

$ java17 -showversion -cp test.jar -XX:ArchiveClassesAtExit=test.jsa \
  -Djdk.internal.lambda.dumpProxyClasses=DUMP_CLASS_FILES \
  -Xlog:cds Test

$ java17 -showversion -cp test.jar -XX:SharedArchiveFile=test.jsa -Xlog:cds Test
[....]
java version "17" 2021-09-14 LTS
Java(TM) SE Runtime Environment (build 17+35-LTS-2724)
Java HotSpot(TM) 64-Bit Server VM (build 17+35-LTS-2724, mixed mode, sharing)
Exception in thread "main" java.lang.NullPointerException
	at java.base/java.util.Optional.ifPresent(Optional.java:178)
	at Tester.test(Unknown Source)
	at Test.main(Unknown Source)

=========================================
Note that the generated lambd proxy class used "ldc ... Dynamic" for getting a MethodHandle to  Base::provideDownstreamSubscription, because the target method is a protected method in a different package. While this method is accessible from Tester (it's from a super type of Tester), it's not accessible from the lambda proxy class.

See here for more info: https://github.com/openjdk/jdk/blob/522b65743ca10fcba0a27d25b8fa11319999e228/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java#L183-L191

$ find DUMP_CLASS_FILES | grep Tester
DUMP_CLASS_FILES/Tester$$Lambda$1.class
$ javap -c -private 'DUMP_CLASS_FILES/Tester$$Lambda$1.class'
final class Tester$$Lambda$1 implements java.util.function.Consumer {
  private final Tester arg$1;

  private Tester$$Lambda$1(Tester);
    Code:
       0: aload_0
       1: invokespecial #13                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: aload_1
       6: putfield      #15                 // Field arg$1:LTester;
       9: return

  public void accept(java.lang.Object);
    Code:
       0: ldc           #28                 // Dynamic #0:_:Ljava/lang/invoke/MethodHandle;
       2: aload_0
       3: getfield      #15                 // Field arg$1:LTester;
       6: aload_1
       7: checkcast     #30                 // class java/lang/String
      10: invokevirtual #36                 // Method java/lang/invoke/MethodHandle.invokeExact:(LTester;Ljava/lang/String;)V
      13: return
}


Comments
Fix request (17u): on behalf of Jan Kratohvil: This bug has been faced by a customer and this backport does work for them. I have run the testsuite on Linux x86_64 and there is no change of the results. Two new testcases are added and they are both Passing. The testcases are still Passing after backporting them to 17u-dev.
21-07-2022

A pull request was submitted for review. URL: https://git.openjdk.org/jdk17u-dev/pull/575 Date: 2022-07-21 10:50:01 +0000
21-07-2022

Changeset: 4dc421ca Author: Ioi Lam <iklam@openjdk.org> Date: 2022-07-19 04:37:28 +0000 URL: https://git.openjdk.org/jdk19/commit/4dc421caa02caedd7061ede6a5ec44dbb6ec738e
19-07-2022

A pull request was submitted for review. URL: https://git.openjdk.org/jdk19/pull/146 Date: 2022-07-18 03:15:02 +0000
18-07-2022

The fix is simple. Will try to target to JDK 19 during RDP1 (ending 2022/07/21)
18-07-2022