Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8280013

Can't invoke default method in non-public interface via reflection

XMLWordPrintable

      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


            mchung Mandy Chung (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: