-
Bug
-
Resolution: Won't Fix
-
P4
-
8, 11, 17, 18, 19
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
$ java -version
openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment Homebrew (build 17.0.1+1)
OpenJDK 64-Bit Server VM Homebrew (build 17.0.1+1, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Attempting to use reflection to invoke a default method inherited in a public class from a non-public interface that extends a public interface fails. Yet this method can be invoked just fine using plain java.
As a result, without using setAccessible(true), it's impossible to perform the same operation using reflection that is permitted when using plain Java.
Is this expected? It seems like in the past Java reflection has always provided a way to do whatever is possible using plain Java, albeit sometimes you have to find the right Method to use.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Files:
============= mypackage/PublicInterface.java
package mypackage;
public interface PublicInterface {
void setFoo(String value);
}
============= mypackage/PackagePrivateInterface.java
package mypackage;
interface PackagePrivateInterface extends PublicInterface {
default void setFooBar() {
this.setFoo("bar");
}
}
============= mypackage/PublicClass.java
package mypackage;
public class PublicClass implements PackagePrivateInterface {
@Override
public void setFoo(String value) {
}
}
============= DefaultMethodReflection.java
import java.lang.reflect.*;
import mypackage.*;
public class DefaultMethodReflection {
public static void main(String[] args) throws Exception {
// We can access PublicClass.setFooBar() using normal java no problem
PublicClass obj = new PublicClass();
obj.setFooBar();
// But doing the same thing through reflection doesn't work
Method method = PublicClass.class.getMethod("setFooBar");
method.invoke(obj); // boom
}
}
============= Shell commands
$ javac -d classes *.java mypackage/*.java
$ java -classpath classes DefaultMethodReflection
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No output
ACTUAL -
Exception in thread "main" java.lang.IllegalAccessException: class DefaultMethodReflection cannot access a member of interface mypackage.PackagePrivateInterface with modifiers "public"
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674)
at java.base/java.lang.reflect.Method.invoke(Method.java:560)
at DefaultMethodReflection.main(DefaultMethodReflection.java:13)
---------- BEGIN SOURCE ----------
See "Steps to Reproduce"
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Method.setAccessible(true)
FREQUENCY : always
$ java -version
openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment Homebrew (build 17.0.1+1)
OpenJDK 64-Bit Server VM Homebrew (build 17.0.1+1, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Attempting to use reflection to invoke a default method inherited in a public class from a non-public interface that extends a public interface fails. Yet this method can be invoked just fine using plain java.
As a result, without using setAccessible(true), it's impossible to perform the same operation using reflection that is permitted when using plain Java.
Is this expected? It seems like in the past Java reflection has always provided a way to do whatever is possible using plain Java, albeit sometimes you have to find the right Method to use.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Files:
============= mypackage/PublicInterface.java
package mypackage;
public interface PublicInterface {
void setFoo(String value);
}
============= mypackage/PackagePrivateInterface.java
package mypackage;
interface PackagePrivateInterface extends PublicInterface {
default void setFooBar() {
this.setFoo("bar");
}
}
============= mypackage/PublicClass.java
package mypackage;
public class PublicClass implements PackagePrivateInterface {
@Override
public void setFoo(String value) {
}
}
============= DefaultMethodReflection.java
import java.lang.reflect.*;
import mypackage.*;
public class DefaultMethodReflection {
public static void main(String[] args) throws Exception {
// We can access PublicClass.setFooBar() using normal java no problem
PublicClass obj = new PublicClass();
obj.setFooBar();
// But doing the same thing through reflection doesn't work
Method method = PublicClass.class.getMethod("setFooBar");
method.invoke(obj); // boom
}
}
============= Shell commands
$ javac -d classes *.java mypackage/*.java
$ java -classpath classes DefaultMethodReflection
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No output
ACTUAL -
Exception in thread "main" java.lang.IllegalAccessException: class DefaultMethodReflection cannot access a member of interface mypackage.PackagePrivateInterface with modifiers "public"
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674)
at java.base/java.lang.reflect.Method.invoke(Method.java:560)
at DefaultMethodReflection.main(DefaultMethodReflection.java:13)
---------- BEGIN SOURCE ----------
See "Steps to Reproduce"
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Method.setAccessible(true)
FREQUENCY : always