This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: static constructors and GC initialization
- To: "Boehm, Hans" <hans_boehm at hp dot com>
- Subject: Re: static constructors and GC initialization
- From: Bryce McKinlay <bryce at albatross dot co dot nz>
- Date: Wed, 31 Jan 2001 14:53:58 +1300
- CC: java at gcc dot gnu dot org
- References: <140D21516EC2D3119EE700902787664401E3A888@hplex1.hpl.hp.com>
"Boehm, Hans" wrote:
> I suspect the issue here is that list of dynamic libraries was somehow
> invalid when it tried to walk it, and it thus ends up trying to mark from a
> region of memory that isn't mapped yet.
That makes sense to me.
> Alternatively, it's somehow
> It would be nice to know more about what's happening, e.g. the fault address
> (i.e. the value of "limit" in mark.c), and the output of GC_dump() when it
> fails, if that's possible.
I already wrote a patch to remove all the static c++ initializers from libgcj
(see below), so I'm not seeing the crash any more in my local tree. I'll send
you this info if I can reproduce it again later.
Unfortunatly sprof still refuses to have anything to do with libgcj.so. I
don't know why. It works fine with libgcjgc.so and libstdc++-v3.so. Thats
unfortunate because it looks like a rather useful profiling tool considering it
works with threads, and we don't need to compile with any special options.
$ sprof libgcj.so.1 profile/libgcj.so.1.profile
sprof: failed to load shared object `libgcj.so.1'
regards
[ bryce ]
Index: defineclass.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/defineclass.cc,v
retrieving revision 1.13
diff -u -r1.13 defineclass.cc
--- defineclass.cc 2000/10/20 23:25:57 1.13
+++ defineclass.cc 2001/01/30 06:52:22
@@ -30,6 +30,7 @@
#endif
#include <java-cpool.h>
#include <gcj/cni.h>
+#include <jvm.h>
#include <java/lang/Class.h>
#include <java/lang/Float.h>
@@ -44,10 +45,7 @@
#include <java/lang/IncompatibleClassChangeError.h>
#include <java/lang/reflect/Modifier.h>
-// we don't verify method names that match these.
-static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
-static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
-
+using namespace gcj;
// these go in some seperate functions, to avoid having _Jv_InitClass
// inserted all over the place.
Index: interpret.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/interpret.cc,v
retrieving revision 1.22
diff -u -r1.22 interpret.cc
--- interpret.cc 2000/10/20 23:25:57 1.22
+++ interpret.cc 2001/01/30 06:52:22
@@ -40,7 +40,7 @@
#include <alloca.h>
#endif
-static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
+using namespace gcj;
static void throw_internal_error (char *msg)
__attribute__ ((__noreturn__));
Index: jni.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/jni.cc,v
retrieving revision 1.36
diff -u -r1.36 jni.cc
--- jni.cc 2001/01/27 19:30:31 1.36
+++ jni.cc 2001/01/30 06:52:23
@@ -47,6 +47,8 @@
#include <java-interp.h>
+using namespace gcj;
+
// FIXME: remove these defines.
#define ClassClass java::lang::Class::class$
#define ObjectClass java::lang::Object::class$
@@ -1479,9 +1481,6 @@
jboolean)
{
using namespace java::lang::reflect;
-
- // FIXME.
- static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
jobject result = NULL;
Index: prims.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/prims.cc,v
retrieving revision 1.46
diff -u -r1.46 prims.cc
--- prims.cc 2001/01/17 08:13:06 1.46
+++ prims.cc 2001/01/30 06:52:23
@@ -510,22 +510,50 @@
+/*
#define DECLARE_PRIM_TYPE(NAME, SIG, LEN) \
_Jv_ArrayVTable _Jv_##NAME##VTable; \
java::lang::Class _Jv_##NAME##Class ((jobject) #NAME, \
- (jbyte) SIG, (jint) LEN, \
- (jobject) &_Jv_##NAME##VTable);
+ (jbyte) SIG, (jint) LEN);
+*/
-DECLARE_PRIM_TYPE(byte, 'B', 1);
-DECLARE_PRIM_TYPE(short, 'S', 2);
-DECLARE_PRIM_TYPE(int, 'I', 4);
-DECLARE_PRIM_TYPE(long, 'J', 8);
-DECLARE_PRIM_TYPE(boolean, 'Z', 1);
-DECLARE_PRIM_TYPE(char, 'C', 2);
-DECLARE_PRIM_TYPE(float, 'F', 4);
-DECLARE_PRIM_TYPE(double, 'D', 8);
-DECLARE_PRIM_TYPE(void, 'V', 0);
+#define DECLARE_PRIM_TYPE(NAME) \
+ _Jv_ArrayVTable _Jv_##NAME##VTable; \
+ java::lang::Class _Jv_##NAME##Class;
+
+/* (jobject) &_Jv_##NAME##VTable); */
+
+DECLARE_PRIM_TYPE(byte);
+DECLARE_PRIM_TYPE(short);
+DECLARE_PRIM_TYPE(int);
+DECLARE_PRIM_TYPE(long);
+DECLARE_PRIM_TYPE(boolean);
+DECLARE_PRIM_TYPE(char);
+DECLARE_PRIM_TYPE(float);
+DECLARE_PRIM_TYPE(double);
+DECLARE_PRIM_TYPE(void);
+void
+_Jv_InitPrimClass (jclass cl, char *cname, char sig, int len,
+ _Jv_ArrayVTable *array_vtable)
+{
+ using namespace java::lang::reflect;
+
+ // We must initialize every field of the class. We do this in the
+ // same order they are declared in Class.h, except for fields that
+ // are initialized to NULL.
+ cl->name = _Jv_makeUtf8Const (cname, -1);
+ cl->accflags = Modifier::PUBLIC | Modifier::FINAL | Modifier::ABSTRACT;
+ cl->method_count = sig;
+ cl->size_in_bytes = len;
+ cl->vtable = JV_PRIMITIVE_VTABLE;
+ cl->state = JV_STATE_DONE;
+ cl->depth = -1;
+ if (sig != 'V')
+ _Jv_NewArrayClass (cl, NULL, (_Jv_VTable *) array_vtable);
+}
+
+
jclass
_Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader)
{
@@ -637,9 +665,52 @@
#endif
+namespace gcj
+{
+ _Jv_Utf8Const *void_signature;
+ _Jv_Utf8Const *clinit_name;
+ _Jv_Utf8Const *init_name;
+ _Jv_Utf8Const *finit_name;
+}
+
+/* Initialize some Utf8 constants declared in jvm.h. */
+void
+initVMConstants ()
+{
+ using namespace gcj;
+
+ void_signature = _Jv_makeUtf8Const ("()V", 3);
+ clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
+ init_name = _Jv_makeUtf8Const ("<init>", 6);
+ finit_name = _Jv_makeUtf8Const ("finit$", 6);
+}
+
+#include <stdio.h>
static void
main_init ()
{
+ static bool init = false;
+
+ if (init)
+ return;
+
+ init = true;
+ initVMConstants ();
+ _Jv_InitThreads ();
+ _Jv_InitGC ();
+ _Jv_InitializeSyncMutex ();
+
+ /* Initialize built-in classes to represent primitive TYPEs. */
+ _Jv_InitPrimClass (&_Jv_byteClass, "byte", 'B', 1, &_Jv_byteVTable);
+ _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);
+
// Turn stack trace generation off while creating exception objects.
_Jv_InitClass (&java::lang::Throwable::class$);
java::lang::Throwable::trace_enabled = 0;
Index: resolve.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/resolve.cc,v
retrieving revision 1.19
diff -u -r1.19 resolve.cc
--- resolve.cc 2000/10/06 01:49:31 1.19
+++ resolve.cc 2001/01/30 06:52:23
@@ -34,6 +34,8 @@
#ifdef INTERPRETER
+using namespace gcj;
+
static void throw_internal_error (char *msg)
__attribute__ ((__noreturn__));
static void throw_class_format_error (jstring msg)
@@ -53,9 +55,6 @@
jboolean,
jint);
-
-// We need to know the name of a constructor.
-static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
static void throw_incompatible_class_change_error (jstring msg)
{
Index: include/jvm.h
===================================================================
RCS file: /cvs/gcc/egcs/libjava/include/jvm.h,v
retrieving revision 1.31
diff -u -r1.31 jvm.h
--- jvm.h 2000/10/09 01:54:50 1.31
+++ jvm.h 2001/01/30 06:52:23
@@ -102,6 +102,15 @@
// FIXME: remove this define.
#define StringClass java::lang::String::class$
+namespace gcj
+{
+ /* Some constants used during lookup of special class methods. */
+ extern _Jv_Utf8Const *void_signature; /* "()V" */
+ extern _Jv_Utf8Const *clinit_name; /* "<clinit>" */
+ extern _Jv_Utf8Const *init_name; /* "<init>" */
+ extern _Jv_Utf8Const *finit_name; /* "finit$", */
+};
+
/* Type of pointer used as finalizer. */
typedef void _Jv_FinalizerFunc (jobject);
Index: java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/Class.h,v
retrieving revision 1.31
diff -u -r1.31 Class.h
--- Class.h 2001/01/17 10:22:32 1.31
+++ Class.h 2001/01/30 06:52:23
@@ -14,7 +14,6 @@
#pragma interface
-#include <stddef.h>
#include <java/lang/Object.h>
#include <java/lang/String.h>
#include <java/net/URL.h>
@@ -52,6 +51,7 @@
struct _Jv_Field;
struct _Jv_VTable;
+struct _Jv_ArrayVTable;
union _Jv_word;
struct _Jv_Constants
@@ -197,19 +197,20 @@
// finalization
void finalize ();
- Class () {};
-
// This constructor is used to create Class object for the primitive
// types. See prims.cc.
- Class (jobject cname, jbyte sig, jint len, jobject array_vtable)
- {
- using namespace java::lang::reflect;
- _Jv_Utf8Const *_Jv_makeUtf8Const (char *s, int len);
-
+ Class ()
+ {
// C++ ctors set the vtbl pointer to point at an offset inside the vtable
// object. That doesn't work for Java, so this hack adjusts it back.
void *p = ((void **)this)[0];
((void **)this)[0] = (void *)((char *)p-2*sizeof (void *));
+ };
+/*
+ Class (jobject cname, jbyte sig, jint len)
+ {
+ using namespace java::lang::reflect;
+ _Jv_Utf8Const *_Jv_makeUtf8Const (char *s, int len);
// We must initialize every field of the class. We do this in the
// same order they are declared in Class.h, except for fields that
@@ -224,7 +225,7 @@
if (method_count != 'V')
_Jv_NewArrayClass (this, NULL, (_Jv_VTable *) array_vtable);
}
-
+*/
static java::lang::Class class$;
private:
@@ -291,6 +292,9 @@
_Jv_VTable *array_vtable = 0);
friend jclass _Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
java::lang::ClassLoader *loader);
+
+ // in prims.cc
+ friend void _Jv_InitPrimClass (jclass, char *, char, int, _Jv_ArrayVTable *);
friend void _Jv_PrepareCompiledClass (jclass);
friend void _Jv_PrepareConstantTimeTables (jclass);
Index: java/lang/natClass.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/natClass.cc,v
retrieving revision 1.35
diff -u -r1.35 natClass.cc
--- natClass.cc 2001/01/17 10:22:32 1.35
+++ natClass.cc 2001/01/30 06:52:23
@@ -60,17 +60,21 @@
#define FieldClass java::lang::reflect::Field::class$
#define ConstructorClass java::lang::reflect::Constructor::class$
-// Some constants we use to look up the class initializer.
-static _Jv_Utf8Const *void_signature = _Jv_makeUtf8Const ("()V", 3);
-static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
-static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
-static _Jv_Utf8Const *finit_name = _Jv_makeUtf8Const ("finit$", 6);
-// The legacy `$finit$' method name, which still needs to be
-// recognized as equivalent to the now prefered `finit$' name.
-static _Jv_Utf8Const *finit_leg_name = _Jv_makeUtf8Const ("$finit$", 7);
-
+using namespace gcj;
+
+static inline bool
+isHiddenMethod (_Jv_Method *method)
+{
+ if (method->name == NULL
+ || _Jv_equalUtf8Consts (method->name, clinit_name)
+ || _Jv_equalUtf8Consts (method->name, init_name)
+ || _Jv_equalUtf8Consts (method->name, finit_name))
+ return true;
+ return false;
+}
+
jclass
java::lang::Class::forName (jstring className, java::lang::ClassLoader *loader)
{
@@ -332,12 +336,7 @@
for (i = max; --i >= 0; )
{
_Jv_Method *method = &methods[i];
- if (method->name == NULL
- || _Jv_equalUtf8Consts (method->name, clinit_name)
- || _Jv_equalUtf8Consts (method->name, init_name)
- || _Jv_equalUtf8Consts (method->name, finit_name)
- // Backward compatibility hack: match the legacy `$finit$' name
- || _Jv_equalUtf8Consts (method->name, finit_leg_name))
+ if (isHiddenMethod (method))
continue;
numMethods++;
}
@@ -348,13 +347,8 @@
for (i = 0; i < max; i++)
{
_Jv_Method *method = &methods[i];
- if (method->name == NULL
- || _Jv_equalUtf8Consts (method->name, clinit_name)
- || _Jv_equalUtf8Consts (method->name, init_name)
- || _Jv_equalUtf8Consts (method->name, finit_name)
- // Backward compatibility hack: match the legacy `$finit$' name
- || _Jv_equalUtf8Consts (method->name, finit_leg_name))
- continue;
+ if (isHiddenMethod (method))
+ continue;
java::lang::reflect::Method* rmethod
= new java::lang::reflect::Method ();
rmethod->offset = (char*) method - (char*) methods;
@@ -513,12 +507,7 @@
for (int i = isPrimitive () ? 0 : method_count; --i >= 0; )
{
_Jv_Method *method = &methods[i];
- if (method->name == NULL
- || _Jv_equalUtf8Consts (method->name, clinit_name)
- || _Jv_equalUtf8Consts (method->name, init_name)
- || _Jv_equalUtf8Consts (method->name, finit_name)
- // Backward compatibility hack: match the legacy `$finit$' name
- || _Jv_equalUtf8Consts (method->name, finit_leg_name))
+ if (isHiddenMethod (method))
continue;
// Only want public methods.
if (! java::lang::reflect::Modifier::isPublic (method->accflags))
Index: java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.28
diff -u -r1.28 natClassLoader.cc
--- natClassLoader.cc 2001/01/08 23:28:55 1.28
+++ natClassLoader.cc 2001/01/30 06:52:23
@@ -420,17 +420,8 @@
void
_Jv_RegisterClasses (jclass *classes)
{
- static bool init = false;
-
- if (! init)
- {
- init = true;
- _Jv_InitThreads ();
- _Jv_InitGC ();
- _Jv_InitializeSyncMutex ();
- }
-
- JvSynchronize sync (&ClassClass);
+ // FIXME
+ //JvSynchronize sync (&ClassClass);
for (; *classes; ++classes)
{
jclass klass = *classes;
@@ -594,16 +585,18 @@
JvAssert (ObjectClass.vtable_method_count == NUM_OBJECT_METHODS);
int dm_count = ObjectClass.vtable_method_count;
- // Create a new vtable by copying Object's vtable (except the
- // class pointer, of course). Note that we allocate this as
- // unscanned memory -- the vtables are handled specially by the
- // GC.
- int size = (sizeof (_Jv_VTable) + ((dm_count - 1) * sizeof (void *)));
_Jv_VTable *vtable;
if (array_vtable)
vtable = array_vtable;
else
- vtable = (_Jv_VTable *) _Jv_AllocBytes (size);
+ {
+ // Create a new vtable by copying Object's vtable (except the
+ // class pointer, of course). Note that we allocate this as
+ // unscanned memory -- the vtables are handled specially by the
+ // GC.
+ int size = (sizeof (_Jv_VTable) + ((dm_count - 1) * sizeof (void *)));
+ vtable = (_Jv_VTable *) _Jv_AllocBytes (size);
+ }
vtable->clas = array_class;
memcpy (vtable->method, ObjectClass.vtable->method,
dm_count * sizeof (void *));