This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Serious bug in _Jv_InitPrimClass (I think)
- From: "Peter Blemel" <pblemel at hotmail dot com>
- To: java-patches at gcc dot gnu dot org
- Date: Fri, 23 Jul 2004 01:33:14 -0600
- Subject: Serious bug in _Jv_InitPrimClass (I think)
- Bcc:
Hello World,
I'm presently exploring why libgcj throws an out of memory exception when I
know very well that it's not out of memory. The answer appears to lie in
an evil chain of events, which I am not sure how to fix -- so I am
soliciting advice. It all starts when _Jv_NewPrimArray exposes a
fundamental problem.
Take a look at the stack dump :
** NOTE ** Whilest trying to sort all of this out I decided to try the GCC
3.4.1 libjava to see if it had the same problem. I can't use 3.4.1 g++/gcj
due to a varargs issue so on a whim I decided to put 3.4.1's libjava in my
GCC 3.3.1 tool chain. The following call stack shows a path of
"gcc-3.3.1-2" but this is in fact gcc 3.4.1's libjava code dropped into the
3.3.1 tool chain. The problem is the same in either version, but it's too
late at night to revert to the original libjava just to illustrate the bug.
I hope that's not too confusing :-)
(gdb) where
#0 _Jv_NewPrimArray (eltype=0x4216248, count=16) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/prims.cc:527
#1 0x04028d30 in java.lang.StringBuffer.StringBuffer(int) (this=0x0,
capacity=16) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/StringBuffer.java:130
#2 0x04018a28 in
java::lang::Runtime::insertSystemProperties(java::util::Properties*)
(newprops=0x1024b8) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natRuntime.cc:573
#3 0x04026048 in java.lang.Runtime.<clinit>() () at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/Runtime.java:111
#4 0x04014860 in java::lang::Class::initializeClass() (this=0x41ca15c) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClass.cc:808
#5 0x0402b358 in java.lang.System.<clinit>() () at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/System.java:110
#6 0x04014860 in java::lang::Class::initializeClass() (this=0x41cbda4) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClass.cc:808
#7 0x0402a880 in java.lang.System.getSecurityManager() () at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/System.java:251
#8 0x04021400 in java.lang.ClassLoader.getSystemClassLoader() () at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/ClassLoader.java:727
#9 0x0401747c in _Jv_FindClass(_Jv_Utf8Const*, java::lang::ClassLoader*)
(name=0x4210000, loader=0x1024b8) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClassLoader.cc:488
#10 0x0400348c in _Jv_FindClassFromSignature(char*,
java::lang::ClassLoader*) (sig=0x4216248 "", loader=0x0) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/prims.cc:689
#11 0x040034c8 in _Jv_FindClassFromSignature(char*,
java::lang::ClassLoader*) (sig=0x4216248 "", loader=0x0) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/prims.cc:693
#12 0x04016e58 in _Jv_PrepareCompiledClass(java::lang::Class*)
(klass=0x41de1f0) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClassLoader.cc:213
#13 0x04014950 in java::lang::Class::initializeClass() (this=0x41de1f0) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClass.cc:732
#14 0x04002d1c in _Jv_AllocObjectNoFinalizer (klass=0x41de1f0, size=28) at
Class.h:279
#15 0x0402e994 in java.lang.VMClassLoader.<clinit>() () at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/VMClassLoader.java:78
#16 0x04014860 in java::lang::Class::initializeClass() (this=0x101b08) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClass.cc:808
#17 0x0402e6d8 in java.lang.VMClassLoader.getSystemClassLoader() () at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/VMClassLoader.java:276
#18 0x04021c60 in java.lang.ClassLoader.<clinit>() () at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/ClassLoader.java:156
#19 0x04014860 in java::lang::Class::initializeClass() (this=0x41c735c) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClass.cc:808
#20 0x040213fc in java.lang.ClassLoader.getSystemClassLoader() () at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/ClassLoader.java:725
#21 0x0401747c in _Jv_FindClass(_Jv_Utf8Const*, java::lang::ClassLoader*)
(name=0x4210000, loader=0x1) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClassLoader.cc:488
#22 0x0400348c in _Jv_FindClassFromSignature(char*,
java::lang::ClassLoader*) (sig=0x4216248 "", loader=0x0) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/prims.cc:689
#23 0x040034c8 in _Jv_FindClassFromSignature(char*,
java::lang::ClassLoader*) (sig=0x4216248 "", loader=0x0) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/prims.cc:693
#24 0x04016e58 in _Jv_PrepareCompiledClass(java::lang::Class*)
(klass=0x41c53c4) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClassLoader.cc:213
#25 0x04014950 in java::lang::Class::initializeClass() (this=0x41c53c4) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClass.cc:732
#26 0x04002d1c in _Jv_AllocObjectNoFinalizer (klass=0x41c53c4, size=108) at
Class.h:279
#27 0x04002d3c in _Jv_AllocObject (klass=0x412db54, size=0) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/prims.cc:421
#28 0x04017544 in _Jv_NewClass(_Jv_Utf8Const*, java::lang::Class*,
java::lang::ClassLoader*) (name=0x412d190, superclass=0x0, loader=0x41c53dc)
at Class.h:245
#29 0x0401765c in _Jv_NewArrayClass(java::lang::Class*,
java::lang::ClassLoader*, _Jv_VTable*) (element=0x4215f50, loader=0x0,
array_vtable=0x4) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/java/lang/natClassLoader.cc:591
#30 0x0400337c in _Jv_InitPrimClass(java::lang::Class*, char*, char, int,
_Jv_ArrayVTable*) (cl=0x4215f50, cname=0x0, sig=66 'B', len=1,
array_vtable=0x4215f30) at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/prims.cc:657
#31 0x04003a90 in _Jv_CreateJavaVM(void*) () at
/cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/prims.cc:916
#32 0x04003cec in _Jv_RunMain(java::lang::Class*, char const*, int, char
const**, bool) (klass=0x1, name=0x0, argc=69297168, argv=0x4215f30,
is_jar=false) at /cygdrive/c/home/gnu/gcc-3.3.1-2/libjava/prims.cc:990
#33 0x040008ec in main (argc=69297168, argv=0x1) at
/cygdrive/c/DOCUME~1/desk/LOCALS~1/Temp/cclKMPtd.i:11
#34 0x04000a5c in _start ()
#35 0xc011dc88 in ?? ()
Note that at #31 libjava is in CreateJavaVM at the first of the primitive
initializations :
_Jv_InitPrimClass (&_Jv_byteClass, "byte", 'B', 1, &_Jv_byteVTable);
<-- This is Line 916
_Jv_InitPrimClass (&_Jv_shortClass, "short", 'S', 2,
&_Jv_shortVTable);
_Jv_InitPrimClass (&_Jv_intClass, "int", 'I', 4, &_Jv_intVTable);
_Jv_InitPrimClass (&_Jv_longClass, "long", 'J', 8, &_Jv_longVTable);
_Jv_InitPrimClass (&_Jv_booleanClass, "boolean", 'Z', 1,
&_Jv_booleanVTable);
_Jv_InitPrimClass (&_Jv_charClass, "char", 'C', 2, &_Jv_charVTable);
_Jv_InitPrimClass (&_Jv_floatClass, "float", 'F', 4,
&_Jv_floatVTable);
_Jv_InitPrimClass (&_Jv_doubleClass, "double", 'D', 8,
&_Jv_doubleVTable);
_Jv_InitPrimClass (&_Jv_voidClass, "void", 'V', 0, &_Jv_voidVTable);
It is initializing the byte class. So far so good. The problem is at
#0/#1 on the call stack we are using a StringBuffer to satisfy the system
class loader / security manager, which is in turn using the char class -- a
class that has not been initialized yet, and won't be until short, int,
long, and bool have all been initialized! Much bad JuJu here.
The root of "my" problem is that the first statement "int elsize =
eltype->size();" in _Jv_NewPrimArray returns a 0 size. This is problematic
for a number of reasons, the first of which is that the branch prediction
statement
if (__builtin_expect ((size_t) count > (MAX_OBJECT_SIZE - size) / elsize,
false))
divides by elsize (I.e. divide by 0). The result appears to be that the
test fails, and "throw no_memory" results. This explains why I am getting
the exception -- but why doesn't everyone else? This is the fly in the
ointment. Beyond that the Jv_Alloc functions would be passed an incorrect
size due to size + elsize * count == size + 0 * count.
I am in need of insight into how to solve this problem. One obvious thing
to try (in the morning :-) is to initialize char first. I don't know how
many classes use the byte primitive, so this may be a chicken-and-egg
problem. I suspect the real bugfix is to split out the statement @
prims.cc:657
if (sig != 'V')
_Jv_NewArrayClass (cl, NULL, (_Jv_VTable *) array_vtable);
which is the root of all evil in that it starts the chain of events leading
to my doom. In effect, I propose to initialize all non-array primitives
first and then come back and call _Jv_NewArrayClass for everything but the
void class.
What do you think?
Regards,
Peter Blemel
_________________________________________________________________
Discover the best of the best at MSN Luxury Living. http://lexus.msn.com/