bug with ConstantValue fields
Godmar Back
gback@cs.utah.edu
Fri Nov 26 13:06:00 GMT 1999
Hi,
I noticed the following bug in gcj which
a) leads to a segfault in libgcj
b) can cause problems with precise marking of unresolved
static class fields (I don't think that's problem yet in
libgcj, but it's a problem in kaffe where all data referred to
by a class is marked precisely.
If a static field of type String is final, i.e., has the ConstantValue
attribute, gcj won't emit code to convert the utf8 holding the
string's value into an actual java.lang.String object under certain
circumstances.
To verify the problem, enter this program:
public class sf {
private static final String ssss = "Hello, World";
public static void main(String []av) throws Exception {
Class sf = Class.forName("sf");
java.lang.reflect.Field f = sf.getDeclaredField("ssss");
// This crashes in libgcj, btw: System.out.println(f);
System.out.println(f.get(null));
}
}
Then compile it via JDK's javac 1.2 or jikes into sf.class
and run it:
gback@peerless [82](/tmp) > gcj --main=sf sf.class -o sf -g
gback@peerless [83](/tmp) > gdb sf
GNU gdb 4.17.0.4 with Linux/x86 hardware watchpoint and FPU support
This GDB was configured as "i386-redhat-linux"...
(gdb) run
Starting program: /tmp/sf
Program received signal SIGSEGV, Segmentation fault.
0x400a5121 in java.io.PrintStream.println (this=@8061ce0, obj=@8048c5c)
at ../../../libgcj/libjava/java/io/PrintStream.java:215
215 print(obj == null ? "null" : obj.toString(), true);
Current language: auto; currently java
(gdb) bt
#0 0x400a5121 in java.io.PrintStream.println (this=@8061ce0, obj=@8048c5c)
at ../../../libgcj/libjava/java/io/PrintStream.java:215
#1 0x8048b82 in sf.main () at sf.java:10
#2 0x400fad5d in java::lang::FirstThread::run (this=@8062f90)
at ../../../libgcj/libjava/java/lang/natFirstThread.cc:52
#3 0x400b890a in java.lang.Thread.run_ (this=@8062f90)
at ../../../libgcj/libjava/java/lang/Thread.java:119
#4 0x400ff9be in java::lang::Thread::run__ (obj=@8062f90)
at ../../../libgcj/libjava/java/lang/natThread.cc:286
#5 0x4010ee52 in _Jv_ThreadStart (thread=@8062f90,
meth=0x400ff9a0 <java::lang::Thread::run__(java::lang::Object *)>)
at ../../../libgcj/libjava/no-threads.cc:28
#6 0x400ffa3b in java::lang::Thread::start (this=@8062f90)
at ../../../libgcj/libjava/java/lang/natThread.cc:299
#7 0x4008948e in JvRunMain (klass=@8049d60, argc=1, argv=@bffffb04)
at ../../../libgcj/libjava/prims.cc:793
#8 0x8048be5 in main (argc=1, argv=@bffffb04) at /tmp/cc1PZ0Srmain.i:11
(gdb) x/w obj
0x8048c5c <_Utf1Hello__World>: 0x000c798c
The static field still points to the unresolved _Utf1Hello__World.
Normally, assigning strings to static fields is done in the static
initializer of a class. However, if the ConstantValue attribute is used,
javac and jikes don't emit that code. (Use jcf-dump -c
to verify that sf.class does not have a <clinit> method.)
Note, btw, that code such as
System.out.println(ssss);
where ssss is defined as above is compiled into:
16: ldc #1=<String "Hello, World">
18: invokevirtual #17=<Method java.io.PrintStream.println ...>
and not via the GETSTATIC instruction by those compilers.
Presumably, this is considered more efficient since the static
field doesn't have to be assigned.
I think it would be sufficient to set the _Jv_FIELD_CONSTANT_VALUE flag
in the _Jv_Field that's emitted. This would give the run-time system
the necessary information to assign the field even if there's no
assignment in a static initializer. This could be done in
_Jv_PrepareCompiledClass. Thinking about it, if this is done before
<clinit> is invoked, it would even eliminate the need to do these
assignments in <clinit> at all.
Comments?
- Godmar
Note that the problem doesn't occur if gcj is used to create the
.class file: gcj will emit a static initializer even if ssss is not
used at all, or only used through reflection. Compiling from the
.java source works also fine. GCJ doesn't "optimize" the GETSTATIC
instruction away either.
More information about the Java
mailing list