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

Legal programs give IllegalAccessError when run.

    XMLWordPrintable

    Details

    • Subcomponent:
    • Resolved In Build:
      1.2fcs
    • CPU:
      generic, x86, sparc
    • OS:
      solaris_2.5.1, solaris_2.6, windows_nt
    • Verification:
      Not verified

      Description

      We currently have a known problem with programs which legally access
      public/protected members belonging to inaccessible classes.

      Compile the following program:

      ::::::::::::::
      one/DefineFooBar.java
      ::::::::::::::
      package one;
       
      class DefineFooBar {
          public int foo = 3;
          
          protected int bar = 4;
      }
      ::::::::::::::
      one/GrantAccess.java
      ::::::::::::::
      package one;
       
      public class GrantAccess extends DefineFooBar {
      }
      ::::::::::::::
      two/UseFooBar.java
      ::::::::::::::
      package two;
       
      public class UseFooBar extends one.GrantAccess {
          public void use() {
              System.out.println(foo + " " + bar);
          }
       
          public static void main(String[] args) {
              new UseFooBar().use();
          }
      }
      ::::::::::::::

      When it is run, we get an IllegalAccessError:

      ::::::::::::::
      $ java two.UseFooBar
      Exception in thread "main" java.lang.IllegalAccessError: try to access class one/DefineFooBar from class two/UseFooBar
              at two.UseFooBar.use(Compiled Code)
              at two.UseFooBar.main(Compiled Code)
      ::::::::::::::

      This is a caused by a problem in the spec. The JLS section 13.1
      requires that the access to foo be compiled as:

      getfield Field one/DefineFooBar.foo:"I";

      The exact language is "A reference to a field of another class or
      interface must be resolved at compile time to a symbolic reference to
      the class or interface in which the field is declared."

      However, when the VM attempts to verify this access, it does not take
      into account that one.DefineFooBar is a superclass of two.UseFooBar --
      it just knows that one.DefineFooBar is not accessible from UseFooBar
      and throws an exception. This behavior is not likely to change.

      So, there must be some rewording of 13.1 which allows the above code
      to run. Changing the access to one of

      getfield Field one/GrantAccess.foo:"I";
      getfield Field two/UseFooBar.foo:"I";

      will allow the access to succeed on post-1.1 VMs.

      As soon as the spec people decide on an appropriate course, we will
      introduce the appropriate fix in the compiler.

      The same bug exists for method calls as well.

      (Note that the above program is legal: without getting into details,
      section 8.2 defines the members of a type to be all members inherited
      from its direct superclass. This means GrantAccess inherits foo from
      DefineFooBar, and UseFooBar inherits foo from GrantAccess. There is
      no special language restricting access based on the type in which the
      member was initially declared.)

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              tturnidgsunw Todd Turnidge (Inactive)
              Reporter:
              tturnidgsunw Todd Turnidge (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: