This is the mail archive of the java-prs@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

java/8830: Incorrect semantics for Foo.class


>Number:         8830
>Category:       java
>Synopsis:       Incorrect semantics for Foo.class
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Thu Dec 05 13:46:02 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Eric Blake
>Release:        3.2
>Organization:
>Environment:
Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/3.2/specs
Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/3.2/../../../libgcj.spec
rename spec lib to liborig
Configured with: /netrel/src/gcc-3.2-3/configure --enable-languages=c,c++,f77,ja
va --enable-libgcj --enable-threads=posix --with-system-zlib --enable-nls --with
out-included-gettext --enable-interpreter --disable-sjlj-exceptions --disable-ve
rsion-specific-runtime-libs --enable-shared --build=i686-pc-linux --host=i686-pc
-cygwin --target=i686-pc-cygwin --enable-haifa --prefix=/usr --exec-prefix=/usr
--sysconfdir=/etc --libdir=/usr/lib --includedir=/nonexistent/include --libexecd
ir=/usr/sbin
Thread model: posix
gcc version 3.2 20020927 (prerelease)
>Description:
JLS 12.4.1 does not permit class literals to cause class initialization.  GCJ, on the other hand, compiles them to initialize the underlying class, because of the specification of Class.forName().  Javac has always got this wrong, but it was recently corrected in jikes 1.17.  This is also a test in the Jacks test suite.

The sample program below should never initialize Sub, since the only use of Sub is via a class literal (and not a static field, method, or constructor).  Therefore, i should still be 1, not 2, when the println is executed.

Also, gcj does not cache the result when compiled to bytecode, when both javac and jikes do.  Caching is useful, because the reflection overhead of Class.forName is expensive.

(Note that any implementation of class literals that does not match Sun's will break serialization compatibility, since adding or removing cache variables, or changing parameters to class$(), will affect the UID.  But I've already pointed this out as the reason why all classes in libgcj should explicitly state their serialVersionUID.  Also note that Sun has proposed a VM extension in JDK 1.5, which will allow 'ldc CONSTANT_Class' to resolve a class literal, rather than the current hack of invisibly calling Class.forName()).
>How-To-Repeat:
$ cat Foo.java
class Foo
{
  static int i = 1;
  static void m(Class c)
  {
    System.out.println(i);
  }
  public static void main(String[] args)
  {
    m(Sub.class);
  }
}
class Sub extends Foo
{
  static int j = i = 1; // should not execute
}
$ gcj -C Foo.java
$ java Foo
2
$ jikes Foo.java
$ java Foo
1
>Fix:
Currently, gcj emits:
private static Class class$(String s)
{
  try
    {
       return Class.forName(s);
    }
  catch (ClassNotFoundException e)
    {
       throw new NoClassDefFoundError(e.getMessage());
    }
}

and translates Sub.class to class$("Sub")

Jikes emits this:

static Class class$Sub;
static Class class$(String s, boolean arraytype)
{
  try
    {
      Class c = Class.forName(s);
      if (! arraytype)
        c = c.getComponentType();
    }
  catch (ClassNotFoundException e)
    {
      throw (Error) new NoClassDefFoundError().initCause(e);
    }
}

and translates Sub.class to:

(class$Sub == null ? class$Sub = class$("LSub;", false)
                   : class$Sub)

>Release-Note:
>Audit-Trail:
>Unformatted:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]