JDK-4183590 : Illegal access error referencing class objects
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 1.1.7,1.2.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic,windows_nt
  • CPU: generic,x86
  • Submitted: 1998-10-22
  • Updated: 1999-10-29
  • Resolved: 1999-10-29
Related Reports
Duplicate :  
Duplicate :  
Description
8

Name: mf23781			Date: 10/22/98


*Description:
Here's the situation:



File a\a.java:
=================================================================

package a;



public class a
{

public a()
{
	System.out.println("a constructor: " +
        foo.class);
}

}
=================================================================




File a\foo.java:
=================================================================

package a;



public class foo

{

}
=================================================================






File b\b.java:
=================================================================

package b;



public class b extends a.a
{

public b()

{

	System.out.println("b constructor: " +
a.foo.class);

}



public static void main(String args[])

{

	new b();

}

}
=================================================================




Next, compile them with javac in this order (!):
javac a\a.java

javac a\foo.java

javac b\b.java



Now, run them:

java
b.b

a constructor: class a.foo

b constructor: class a.foo


So far, so good, right? Maybe not:

jview b.b

a constructor: class
a.foo
ERROR: java.lang.IllegalAccessError: a/a: field class$a$foo is
inaccessible


OK, then. Time to look at the bytecode:




File a.mocha:
=================================================================

/* Decompiled by Mocha from a.class */
/* Originally compiled from a.java */


package a;

import java.io.PrintStream;



public synchronized class a

{
    static Class class$a$foo;


    public a()
    {
        System.out.println((class$a$foo != null) ? class$a$foo :
(class$a$foo = class$("a.foo")));
    }


    static Class class$(String string)
    {
        try
        {
            return Class.forName(string);
        }
        catch (ClassNotFoundException e)
        {
            throw new NoClassDefFoundError(e.getMessage());
        }
    }
}
=================================================================



File b.mocha:
=================================================================

/* Decompiled by Mocha from b.class */
/* Originally compiled from b.java */



package b;

import a.a;
import java.io.PrintStream;



public synchronized class b extends a
{
    public b()
    {
        System.out.println(new StringBuffer("b constructor:
").append((a.class$a$foo != null) ? a.class$a$foo : (a.class$a$foo =
class$("a.foo"))).toString());
    }

    public static void main(String astring[])
    {
        new b();
    }



    static Class class$(String string)
    {
        try
        {
            return Class.forName(string);
        }
        catch (ClassNotFoundException e)
        {
            throw new NoClassDefFoundError(e.getMessage());
        }
    }

}
=================================================================



So it looks like javac is trying to be smart, and it doesn't create a local
field to hold foo's Class object -- it just shares the one with its parent
class. The only problem is the access specifier on a.class$a$foo. It's
neither public nor protected, so b.b can't access it. This suggests that
there are two problems here:
javac is generating the wrong code. Either it shouldn't have tried to get
b.b to share the field with a.a, or it should have made a.class$a$foo
protected.
Java.exe doesn't throw an exception when that code executes! Jview rightly
throws an IllegalAccessError.


======================================================================

Comments
EVALUATION I believe this was fixed by maddox@Eng. todd.turnidge@Eng 1998-12-01 This bug is reproducible in jdk1.1.8. The compiler does create a local field to hold foo's Class object in jdk1.2, jdk1.2.2, and jdk1.3 (build fcs-L). Here's the jdk1.3 output from javap showing all classes and members of class a.java and b.java. $ jdk13 $ javac a/a.java ; javac a/foo.java; javac b/b.java $ javap -private a/a Compiled from a.java public class a/a extends java.lang.Object { static java.lang.Class class$a$foo; public a/a(); static java.lang.Class class$(java.lang.String); } $ javap -private b/b Compiled from b.java public class b/b extends a.a { static java.lang.Class class$a$foo; public b/b(); public static void main(java.lang.String[]); static java.lang.Class class$(java.lang.String); } This bug is a duplicate of 4106051. iris.garcia@eng 1999-10-28
28-10-1999