This is the mail archive of the java-patches@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]

Serious bug in _Jv_InitPrimClass (I think)



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/


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