JDK-8222411 : JCK lang/LMBD tests fail in Valhalla nestmates repo
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: repo-valhalla
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2019-04-12
  • Updated: 2020-03-18
  • Resolved: 2020-02-21
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.
Other
repo-valhallaFixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
These four JCK lang tests fail with unexpected IllegalAccessError exceptions when run in the Valhalla nestmates repo:

    lang/LMBD/lmbd174/lmbd17402m2001/lmbd17402m2001_rt
    lang/LMBD/lmbd174/lmbd17402m21111/lmbd17402m21111_rt
    lang/LMBD/lmbd174/lmbd17402m1011/lmbd17402m1011_rt
    lang/LMBD/lmbd174/lmbd17402m31011/lmbd17402m31011_rt

Typical failure message is:

failure: unexpectedly method reference evaluation has thrown IllegalAccessError:
java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at javasoft.sqe.tests.lang.lmbd174.lmbd17402m1011.lmbd17402m1011.run(lmbd17402m1011.java:35)
                     ...
Caused by: java.lang.IllegalAccessError: class javasoft.sqe.tests.lang.lmbd174.lmbd17402m1011.MethodInvoker$$Lambda$126\\168 tried to access protected method 'java.lang.String javasoft.sqe.tests.lang.lmbd174.lmbd17402m1011.anotherpkg.MethodSupplierOuter$MethodSupplier.m(java.lang.Object, java.lang.Object, java.lang.Object)' (javasoft.sqe.tests.lang.lmbd174.lmbd17402m1011.MethodInvoker$$Lambda$126\\168 and javasoft.sqe.tests.lang.lmbd174.lmbd17402m1011.anotherpkg.MethodSupplierOuter$MethodSupplier are in unnamed module of loader java.net.URLClassLoader @4ea2e4ff)

Comments
Changeset: https://hg.openjdk.java.net/valhalla/valhalla/rev/f796bd335b45
21-02-2020

Per [~abuckley]: Changing `public` to `protected` on a member declaration is binary compatible for some accessors and not binary compatible for other accessors. That's why JLS 13.4.7 says "Changing the declared access of a member or constructor to permit less access ***may*** break compatibility with pre-existing binaries. In the lmbd17402m1011/MethodInvoker.java test. Effectively, it uses a method reference of this form: `<instance of Main> :: <method of Main's supertype>` Because this method reference is in the subtype, and the "receiver" of the method reference is an instance of the subtype, the method reference must evaluate without error at run time, even if the method in the supertype is changed from `public` to `protected`.
06-02-2020

These JCK tests do separate compilation. MethodInvoker is compiled with a public MethodSupplierOuter.MethodSupplier class with public m method. Therefore MethodInvoker.class has the following BSM: BootstrapMethods: 0: #25 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; Method arguments: #32 (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/Long;)Ljava/lang/String; #33 REF_invokeVirtual javasoft/sqe/tests/lang/lmbd174/lmbd17402m21111/anotherpkg/MethodSupplierOuter$MethodSupplier.m:(ILjava/lang/String;J)Ljava/lang/String; #32 (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/Long;)Ljava/lang/String; InnerClasses: public static #41= #2 of #39; // MethodSupplier=class javasoft/sqe/tests/lang/lmbd174/lmbd17402m21111/anotherpkg/MethodSupplierOuter$MethodSupplier of class javasoft/sqe/tests/lang/lmbd174/lmbd17402m21111/anotherpkg/MethodSupplierOuter public static final #46= #42 of #44; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles Then run with a different MethodSupplierOuter$MethodSupplier class with protected m method and hence IAE is thrown. If MethodInvoker.java is recompiled with MethodSupplierOuter$MethodSupplier class with the protected method, the access check will succeed.
05-02-2020

[~sadayapalam] I'm assigning this to you. The resolution for this issue is for JCK team to recompile these tests with a new javac with the fix for JDK-8227415. When it is decided to backport JDK-8227415 or not in an existing release, we can reassign this bug to JCK team to provide specific version of javac be used to recompile these tests.
20-09-2019

Nestmates have to be in the same run-time package. To access cross-package protected members, a bridge method is needed (see JDK-8227415). It means that existing classfile has method reference to a protected member in its superclass in another package will need to be recompiled with JDK 14 javac. We ran into one only JDK test failing with this incompatible change. However we may need to provide a workaround to help transition.
17-09-2019

These tests are failing because the hidden class is trying to invoke a protected method in a class in a different package. For example suppose we had the following classes: class pkg1.foo { protected void m() { } } class pkg2.bar extends pkg1.foo { ... } If class pkg2.bar creates an unsafe anonymous class that calls pkg1.foo.m() then access checking will succeed because the anonymous class's host class, pkg2.bar, is a sub-type of pkg1.foo. But, if pkg2.bar creates a hidden class that calls pkg1.foo.m() then access checking will fail unless the hidden class is also a sub-type of pkg1.foo. I think these tests are failing because they create hidden classes that are not sub-types of the class containing a protected method that they are calling. And, the class containing the protected method is in a different package than the hidden class. (This example assumes that all of these classes are in the same module and have the same defining loader.)
17-09-2019