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

MethodHandles.Lookup.revealDirect performs access checking against wrong class



    • Bug
    • Resolution: Unresolved
    • P4
    • tbd
    • 9
    • core-libs
    • None


      The lookup factory methods of MethodHandles.Lookup perform access checking based on a provided "referenced class", 'refc'. However, the 'revealDirect' method checks access against the *declaring* class. As a result, a straightforward back-to-back findStatic/revealDirect can fail.


      package p1;
      class A {
          public static void staticMethod() {}
          public void instanceMethod() {}


      package p1;
      public class B extends A {}


      package p2;
      public class C extends p1.B {}


      import java.lang.invoke.*;

      public class Test {
          public static void main(String... args) throws Exception {
              MethodHandles.Lookup lookup = MethodHandles.lookup();
              MethodHandle mh = lookup.findStatic(p2.C.class, "staticMethod", MethodType.methodType(void.class));
              System.out.println("mh: " + mh);
              MethodHandleInfo mhi = lookup.revealDirect(mh);
              System.out.println("mhi: " + mhi);


      Program output:

      mh: MethodHandle()void
      Exception in thread "main" java.lang.IllegalArgumentException: java.lang.IllegalAccessException: class is not public: p1.A.staticMethod()void/invokeStatic, from Test (unnamed module @3834d63f)
      at java.base/java.lang.invoke.MethodHandles$Lookup.revealDirect(MethodHandles.java:1835)
      at Test.main(Test.java:10)
      Caused by: java.lang.IllegalAccessException: class is not public: p1.A.staticMethod()void/invokeStatic, from Test (unnamed module @3834d63f)
      at java.base/java.lang.invoke.MemberName.makeAccessException(MemberName.java:915)
      at java.base/java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:2022)
      at java.base/java.lang.invoke.MethodHandles$Lookup.revealDirect(MethodHandles.java:1832)
      ... 1 more


      If I use 'findVirtual' to inspect 'instanceMethod' instead, there is no access checking error, although the result doesn't provide accurate information, apparently in an attempt to workaround the access checking problem:

      mh: MethodHandle(C)void
      mhi: invokeVirtual p1.B.instanceMethod:()void

      (Note that p1.B is neither the declaring class nor the referenced class.)


      This issue is closely tied to JDK-8068253: direct method handles ought to be preserving their referenced class rather than assuming the declaring class is sufficient.

      Note that, because of this problem, LambdaMetafactory is unable to properly handle some inputs (such as for 'p2.C::staticMethod'), and as a workaround javac currently generates "bridge" lambda methods (see, e.g., JDK-8068254).


        Issue Links



              mchung Mandy Chung
              dlsmith Dan Smith
              0 Vote for this issue
              3 Start watching this issue