declaring class of a default method Was: Bug 8027734

Joel Borggren-Franck joel.franck at oracle.com
Tue Nov 12 06:25:07 PST 2013


Hi Yumin,

Basically this is due to a difference in declaring class for a Method
representing a default method vs a normal Method.

On 2013-11-11, Yumin Qi wrote:
> Hi, Joel
> 
>   This bug is a SQE testing bug, see
> https://bugs.openjdk.java.net/browse/JDK-8027734
> <https://bugs.openjdk.java.net/browse/JDK-8027734>
> 
>   I have commented with the exception stacktrace.
> 

This is easy to reproduce without VM sqe frameworks:

p1/I.java:

package p1;
interface I {
    default void m() {
        System.out.println("Foo!");
    }
}

p2/J.java:

package p1;
public interface J extends I {}

p2/C.java:

package p2;
import p1.J;
import java.lang.reflect.*;
public class C {
    public static void main(String[] args) throws Exception {
        Method m = J.class.getMethod("m", (Class<?>[])null);
        System.out.println(m + " declaring class: " + m.getDeclaringClass());
        m.invoke(new J() {});
    }
}

Compiling and running this will print:

$ java p2.C
public default void p1.I.m() declaring class: interface p1.I
Exception in thread "main" java.lang.IllegalAccessException: Class p2.C
can not access a member of class p1.I with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:101)
    at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:295)
    at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:287)
    at java.lang.reflect.Method.invoke(Method.java:476)
    at p2.C.main(C.java:8)

Note that the delcaring class of m is "interface p1.I".

Changing this to classes instead:

package p3;
class A {
    public void m() {
        System.out.println("Foo!");
    }
}

package p3;
public class B extends A {}

package p4;
import p3.B;
import java.lang.reflect.*;
public class C2 {
    public static void main(String[] args) throws Exception {
        Method m = B.class.getMethod("m", (Class<?>[])null);
        System.out.println(m + " declaring class: " + m.getDeclaringClass());
        m.invoke(new B() {});
    }
}

And running this gives:

java p4.C2
public void p3.B.m() declaring class: class p3.B
Foo!

Note that even though m is lexically declared in class A
m.getDeclaringClass() outputs _p3.B_ as it's declaring class.

I'm not sure how we should fix this, but my first impression is that the
VM is wrong here when creating the default method Method in the
interface example.

cheers
/Joel


More information about the hotspot-runtime-dev mailing list