-
Bug
-
Resolution: Fixed
-
P2
-
8
JSR 335 spec, chapter "15.28.2 Run-time Evaluation of Method References" contains following assertion:
If the method reference has the form ExpressionName :: NonWildTypeArgumentsopt Identifier or Primary :: NonWildTypeArgumentsopt Identifier, the body of the invocation method has the effect of invoking the compile-time declaration of the method reference, as described in 15.12.4.3, 15.12.4.4, 15.12.4.5.[jsr335-15.28.2-41]
This assertions refers to chapter "15.12.4.3. Check Accessibility of Type and Method" which contains following assertions:
Let C be the class containing the method invocation, and let T be the qualifying type of the method invocation (§13.1), and let m be the name of the method as determined at compile-time (§15.12.3).
...
If m is private, then m is accessible if and only if C is T, or C encloses T, or T encloses C, or T and C are both enclosed by a third class.
...
According to these assertions MethodInvoker.invoke should succeed for following three cases:
case 1:
class MethodInvoker {
public static void invoke() {
MethodSupplier ms = new MethodSupplier();
MyFunctionalInterface1 fi = ms::m;
fi.invokeMethodReference();
}
static class MethodSupplier {
private void m() {
System.out.println("m");
}
}
}
case 2:
class MethodSupplier {
private void m() {
System.out.println("m");
}
static class MethodInvoker {
public static void invoke() {
MethodSupplier ms = new MethodSupplier();
MyFunctionalInterface2 fi = ms::m;
fi.invokeMethodReference();
}
}
}
case 3:
class ThirdClass {
static class MethodSupplier {
private void m() {
System.out.println("m");
}
}
static class MethodInvoker {
public static void invoke() {
MethodSupplier ms = new MethodSupplier();
MyFunctionalInterface3 fi = ms::m;
fi.invokeMethodReference();
}
}
}
but all of these 3 cases fail with following stack traces correspondingly:
case1:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:491)
at Test1.main(Test1.java:20)
Caused by: java.lang.IncompatibleClassChangeError
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:383)
at MethodInvoker.invoke(Test1.java:8)
... 5 more
Caused by: java.lang.IllegalAccessException: member is private: MethodInvoker$MethodSupplier.m()void/invokeSpecial, from MethodInvoker
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:744)
at java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:1129)
at java.lang.invoke.MethodHandles$Lookup.checkMethod(MethodHandles.java:1092)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1203)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethod(MethodHandles.java:1193)
at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1285)
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:381)
... 6 more
case 2:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:491)
at Test2.main(Test2.java:21)
Caused by: java.lang.IncompatibleClassChangeError
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:383)
at MethodSupplier$MethodInvoker.invoke(Test2.java:13)
... 5 more
Caused by: java.lang.IllegalAccessException: member is private: MethodSupplier.m()void/invokeSpecial, from MethodSupplier$MethodInvoker
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:744)
at java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:1129)
at java.lang.invoke.MethodHandles$Lookup.checkMethod(MethodHandles.java:1092)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1203)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethod(MethodHandles.java:1193)
at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1285)
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:381)
... 6 more
case 3:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:491)
at Test3.main(Test3.java:24)
Caused by: java.lang.IncompatibleClassChangeError
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:383)
at ThirdClass$MethodInvoker.invoke(Test3.java:16)
... 5 more
Caused by: java.lang.IllegalAccessException: member is private: ThirdClass$MethodSupplier.m()void/invokeSpecial, from ThirdClass$MethodInvoker
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:744)
at java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:1129)
at java.lang.invoke.MethodHandles$Lookup.checkMethod(MethodHandles.java:1092)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1203)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethod(MethodHandles.java:1193)
at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1285)
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:381)
... 6 more
This was reproduced on b100, platform: Windows7x64.
The minimized tests are attached in a single archive.
In order to reproduce case 1, 2 and 3 please run Test1.main, Test2.main and Test3.main from attached archive correspondingly.
If the method reference has the form ExpressionName :: NonWildTypeArgumentsopt Identifier or Primary :: NonWildTypeArgumentsopt Identifier, the body of the invocation method has the effect of invoking the compile-time declaration of the method reference, as described in 15.12.4.3, 15.12.4.4, 15.12.4.5.[jsr335-15.28.2-41]
This assertions refers to chapter "15.12.4.3. Check Accessibility of Type and Method" which contains following assertions:
Let C be the class containing the method invocation, and let T be the qualifying type of the method invocation (§13.1), and let m be the name of the method as determined at compile-time (§15.12.3).
...
If m is private, then m is accessible if and only if C is T, or C encloses T, or T encloses C, or T and C are both enclosed by a third class.
...
According to these assertions MethodInvoker.invoke should succeed for following three cases:
case 1:
class MethodInvoker {
public static void invoke() {
MethodSupplier ms = new MethodSupplier();
MyFunctionalInterface1 fi = ms::m;
fi.invokeMethodReference();
}
static class MethodSupplier {
private void m() {
System.out.println("m");
}
}
}
case 2:
class MethodSupplier {
private void m() {
System.out.println("m");
}
static class MethodInvoker {
public static void invoke() {
MethodSupplier ms = new MethodSupplier();
MyFunctionalInterface2 fi = ms::m;
fi.invokeMethodReference();
}
}
}
case 3:
class ThirdClass {
static class MethodSupplier {
private void m() {
System.out.println("m");
}
}
static class MethodInvoker {
public static void invoke() {
MethodSupplier ms = new MethodSupplier();
MyFunctionalInterface3 fi = ms::m;
fi.invokeMethodReference();
}
}
}
but all of these 3 cases fail with following stack traces correspondingly:
case1:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:491)
at Test1.main(Test1.java:20)
Caused by: java.lang.IncompatibleClassChangeError
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:383)
at MethodInvoker.invoke(Test1.java:8)
... 5 more
Caused by: java.lang.IllegalAccessException: member is private: MethodInvoker$MethodSupplier.m()void/invokeSpecial, from MethodInvoker
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:744)
at java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:1129)
at java.lang.invoke.MethodHandles$Lookup.checkMethod(MethodHandles.java:1092)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1203)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethod(MethodHandles.java:1193)
at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1285)
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:381)
... 6 more
case 2:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:491)
at Test2.main(Test2.java:21)
Caused by: java.lang.IncompatibleClassChangeError
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:383)
at MethodSupplier$MethodInvoker.invoke(Test2.java:13)
... 5 more
Caused by: java.lang.IllegalAccessException: member is private: MethodSupplier.m()void/invokeSpecial, from MethodSupplier$MethodInvoker
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:744)
at java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:1129)
at java.lang.invoke.MethodHandles$Lookup.checkMethod(MethodHandles.java:1092)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1203)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethod(MethodHandles.java:1193)
at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1285)
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:381)
... 6 more
case 3:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:491)
at Test3.main(Test3.java:24)
Caused by: java.lang.IncompatibleClassChangeError
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:383)
at ThirdClass$MethodInvoker.invoke(Test3.java:16)
... 5 more
Caused by: java.lang.IllegalAccessException: member is private: ThirdClass$MethodSupplier.m()void/invokeSpecial, from ThirdClass$MethodInvoker
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:744)
at java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:1129)
at java.lang.invoke.MethodHandles$Lookup.checkMethod(MethodHandles.java:1092)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1203)
at java.lang.invoke.MethodHandles$Lookup.getDirectMethod(MethodHandles.java:1193)
at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1285)
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:381)
... 6 more
This was reproduced on b100, platform: Windows7x64.
The minimized tests are attached in a single archive.
In order to reproduce case 1, 2 and 3 please run Test1.main, Test2.main and Test3.main from attached archive correspondingly.
- blocks
-
JDK-8022074 IncompatibleClassChangeError when creating method reference to outer class private method
- Closed
- relates to
-
JDK-8010319 Implementation of JEP 181: Nest-Based Access Control
- Resolved
-
JDK-8010319 Implementation of JEP 181: Nest-Based Access Control
- Resolved