This bug comes from compiling ant-1.5.1, specifically ProjectHelperImpl.java. They create a nested static class. In the nested class, they make an explicit reference to the outer class. And finally they refer to a private member of the outer class. Here's a simplification of the code: public class PHI { public static void main( String args[] ) { PHI phi = new PHI(); RH rh = new RH( phi ); rh.setLocator( "TheHound" ); } private String locator; static class RH { PHI phi; public RH( PHI phi ) { this.phi = phi; } public void setLocator( String locator ) { phi.locator = locator; } } } brian@mahogany:Personal/Workshop/Test/ :) gcj -C PHI.java brian@mahogany:Personal/Workshop/Test/ :) gij PHI Exception in thread "main" java.lang.IllegalAccessError at 0x40174218: java.lang.Throwable.Throwable() (/usr/lib/libgcj.so.2) at 0x4016a7c4: java.lang.Error.Error() (/usr/lib/libgcj.so.2) at 0x4016c908: java.lang.LinkageError.LinkageError() (/usr/lib/libgcj.so.2) at 0x4016b6a4: java.lang.IncompatibleClassChangeError.IncompatibleClassChangeError() (/usr/lib/libgcj.so.2) at 0x4016b404: java.lang.IllegalAccessError.IllegalAccessError() (/usr/lib/libgcj.so.2) at 0x40149d5a: _Jv_ResolvePoolEntry(java.lang.Class, int) (/usr/lib/libgcj.so.2) at 0x401516f0: _Jv_InterpMethod.continue1(_Jv_InterpMethodInvocation) (/usr/lib/libgcj.so.2) at 0x40152703: _Jv_InterpMethod.run(ffi_cif, void, ffi_raw, _Jv_InterpMethodInvocation) (/usr/lib/libgcj.so.2) at 0x4014e671: _Jv_InterpMethod.run_normal(ffi_cif, void, ffi_raw, void) (/usr/lib/libgcj.so.2) at 0x4023b114: ?? (??:0) at 0x4023b25f: ffi_call_SYSV (/usr/lib/libgcj.so.2) at 0x4023b227: ffi_raw_call (/usr/lib/libgcj.so.2) at 0x4014e8db: _Jv_InterpMethod.continue1(_Jv_InterpMethodInvocation) (/usr/lib/libgcj.so.2) at 0x40152703: _Jv_InterpMethod.run(ffi_cif, void, ffi_raw, _Jv_InterpMethodInvocation) (/usr/lib/libgcj.so.2) at 0x4014e671: _Jv_InterpMethod.run_normal(ffi_cif, void, ffi_raw, void) (/usr/lib/libgcj.so.2) at 0x4023b114: ?? (??:0) at 0x4015565f: gnu.gcj.runtime.FirstThread.run() (/usr/lib/libgcj.so.2) at 0x4015fb63: java.lang.Thread.run_(java.lang.Object) (/usr/lib/libgcj.so.2) at 0x4023a6a4: ?? (??:0) at 0x403dff76: GC_start_routine (/usr/lib/libgcjgc.so.1) at 0x403f7fa5: ?? (??:0) at 0x4050c8ea: __clone (/lib/libc.so.6) In my personal opinion, i don't think this is a bug. The inner class does have access to the private members of the outer class, but this is through an implicit reference. Static classes don't have the implicit reference. The question is, what is the definied behavior of an explicit reference. So why do i report it? Because obviously other compilers have compiled and executed ProjectHelperImpl successfully. A related PR is 9369. Just hypothetically here, if the compiler does generate a function void setLocator( String Locator ) { this.Locator = Locator } in the outer class PHI, does this function become accessible to the public (or to subclasses)? I hope not, since this would change the definition of the class. Release: gcj-3.2, gij-3.2 Environment: GNU/Debian Linux (woody mostly) How-To-Repeat: gcj -C PHI.java gij PHI
Fix: If the outer data member is protected, there's no error.
still an error on the mainline (): tin:~/src/gnu/gcctest>gcj -C PHI.java tin:~/src/gnu/gcctest>gij PHI Exception in thread "main" java.lang.IllegalAccessError at _Jv_ResolvePoolEntry(java.lang.Class, int) (/home/gates/pinskia/linux/lib/ libgcj.so.4.0.0) at PHI$RH.setLocator(java.lang.String) (Unknown Source) at PHI.main(java.lang.String[]) (Unknown Source) tin:~/src/gnu/gcctest>gcj -C PHI.java -g tin:~/src/gnu/gcctest>gij PHI Exception in thread "main" java.lang.IllegalAccessError at _Jv_ResolvePoolEntry(java.lang.Class, int) (/home/gates/pinskia/linux/lib/ libgcj.so.4.0.0) at PHI$RH.setLocator(java.lang.String) (Unknown Source) at PHI.main(java.lang.String[]) (Unknown Source) tin:~/src/gnu/gcctest>javac PHI.java tin:~/src/gnu/gcctest>!gij gij PHI tin:~/src/gnu/gcctest>gcj -C PHI.java tin:~/src/gnu/gcctest>java PHI tin:~/src/gnu/gcctest>
The native compiler works but gij does not so changing component to libgcj which is where gij is part of.
The JDK java interpreter does accept the code gcj generates. However, javac generates an explicit package-private settor method. That is what gcj should do as well. So, this is probably two bugs: one in libgcj's access checking, and another in gcj itself. The latter is, I believe, a duplicate.
This bug also affects GCJ 3.3.2 on GNU/Linux and 3.3.3 on Cygwin. The class org.w3c.tidy.ParserImpl in the JTidy tool is another test case. http://sourceforge.net/projects/jtidy/
I still see the problem with gcj (GCC) 4.1.2 20061018 (prerelease) (SUSE Linux). It makes problems also with OpenOffice.org when the internally used hsqldb is compiled and used with gcj/gij. Note that it is really a bug. The java documentation says at http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html: --- cut --- A nested class is a member of its enclosing class and, as such, has access to other members of the enclosing class, even if they are declared private. --- cut --- There is another definition in the "Java Language Specification" at http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.1: --- cut --- Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (ยง7.6) that encloses the declaration of the member or constructor. --- cut --- Note that also C++ works this way. The OPOSITE problem is even mentioned in the "Frequently reported non-bugs" at http://gcc.gnu.org/bugs.html#nonbugs_cxx: --- cut --- Nested classes can access private members and types of the containing class. Defect report 45 clarifies that nested classes are members of the class they are nested in, and so are granted access to private members of that class. --- cut ---
All gcj front end bugs have been fixed by the gcj-eclipse branch merge. I'm mass-closing the affected PRs. If you believe one of these was closed in error, please reopen it with a note explaining why. Thanks.