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

IllegalAccessException using method reference to package-private class via publ

    Details

    • CPU:
      x86_64
    • OS:
      linux

      Description

      FULL PRODUCT VERSION :
      openjdk version "1.8.0-jdk8u76-b00"
      OpenJDK Runtime Environment (build 1.8.0-jdk8u76-b00-20151028)
      OpenJDK 64-Bit Server VM (build 25.66-b20151028, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Linux (hostname) 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      I have a package-private class "A" and a public class "B" that extends it. Class A has a public static method "print" that I want to access via a method pointer from class "C", which is in a different package. I use "B::print" as the method pointer, which compiles fine, but I get an IllegalAccessException when I run the code. It looks like the compiler is generating a class file that references A.print() instead of B.print(). The Eclipse compiler (where I originally filed this bug) generates a class file that correctly references B.print(), but the runtime error still occurs.

      Jesper Moller provided some good information in the Eclipse bug I filed:

      https://bugs.eclipse.org/bugs/show_bug.cgi?id=480930#c4

      I was able to work around the issue by making the base class public, but I'd rather leave it package-private, if possible.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Enter the attached code and try to execute the example.b.C class.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The generated class file should contain a reference to the example.a.B.print(int) method. The application should print out a list of integers between 0 and 9.
      ACTUAL -
      The generated class file contains a reference to the example.a.A.print(int) method. Execution fails with the attached error message.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Exception in thread "main" java.lang.IllegalAccessError: tried to access class example.a.A from class example.b.C
      at example.b.C.lambda$main$0(C.java:11)
      at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)
      at java.util.stream.IntPipeline$Head.forEach(IntPipeline.java:557)
      at example.b.C.main(C.java:11)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      // example/a/B.java

      package example.a;

      abstract class A
      {
         public static void print(int value)
         {
            System.out.println(value);
         }
      }

      public class B extends A
      {
         // No additional functionality.
      }

      // example/b/C.java

      package example.b;

      import java.util.stream.IntStream;

      import example.a.B;

      public class C
      {
         public static void main(String[] args)
         {
            IntStream.range(0, 10).forEach(B::print);

            // This line executes fine.
      // IntStream.range(0, 10).forEach(value -> {B.print(value);});
         }
      }

      // Jesper Moller provided this alternate version of C.java in the Eclipse bug I filed:

      package example.b;

      import java.lang.invoke.*;

      import example.c.B;

      public class C {
         public static void main(String[] args) throws Throwable {
           MethodHandles.Lookup me = MethodHandles.lookup();

           MethodType t = MethodType.methodType(void.class);
           MethodType rt = MethodType.methodType(Runnable.class);
           MethodHandle b_print = me.findStatic(B.class, "print", t); // becomes A::print
           CallSite site = LambdaMetafactory.metafactory(me, "run", rt, t, b_print, t);
           MethodHandle factory = site.getTarget();
           Runnable b_print_asRunnable = (Runnable) factory.invoke();
         }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I reluctantly made the base class public to work around this issue. I'd rather not expose the base class, though.

        Attachments

        1. A.java
          0.1 kB
        2. B.java
          0.1 kB
        3. C.java
          0.3 kB

          Issue Links

            Activity

              People

              • Assignee:
                aefimov Aleksej Efimov
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: