JDK-8068254 : Method reference uses wrong qualifying type
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2014-12-24
  • Updated: 2017-01-13
  • Resolved: 2015-01-13
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 8 JDK 9
8u101Fixed 9 b47Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
A reference to a method declared in a package-access class (via a public subtype) compiles to a lambda bridge; the qualifying type in the bridge method is the declaring class, not the referenced class.  This leads to an IllegalAccessError.

---
package p1;
class A {
    public static void m() { System.out.println("A.m"); }
}
---
package p1;
public class B extends A {
}
---
package p2;
public class Test {
    public static void main(String... args) {
        p1.B.m(); // ok
        Runnable r = p1.B::m; r.run(); // runtime error
    }
}
---

$ -> java p2.Test
A.m
Exception in thread "main" java.lang.IllegalAccessError: tried to access class p1.A from class p2.Test
	at p2.Test.lambda$MR$main$m$64fce12b$1(Test.java:7)
	at p2.Test$$Lambda$1/1160460865.run(Unknown Source)
	at p2.Test.main(Test.java:8)

$ -> javap -verbose -private p2.Test
...
  public static void main(java.lang.String...);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
    Code:
      stack=1, locals=2, args_size=1
         0: invokestatic  #2                  // Method p1/B.m:()V
         3: invokedynamic #3,  0              // InvokeDynamic #0:run:()Ljava/lang/Runnable;
         8: astore_1
         9: aload_1
        10: invokeinterface #4,  1            // InterfaceMethod java/lang/Runnable.run:()V
        15: return
...
  private static void lambda$main$0();
    descriptor: ()V
    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=0, locals=0, args_size=0
         0: invokestatic  #5                  // Method p1/A.m:()V
         3: return


Comments
I'll follow up on this one, Thanks.
29-12-2014

The underlying issue -- the reason to use a bridge in the first place -- may be that the MethodHandle API doesn't provide a way to reconstruct the reference via B.m()V, rather than A.m()V. See JDK-8068253.
24-12-2014