This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Patch: RFC: fix system class loader problem
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: 03 May 2005 14:52:38 -0600
- Subject: Patch: RFC: fix system class loader problem
- Reply-to: tromey at redhat dot com
This patch fixes the system class loader problem for the trunk.
The bug is that the class specified to --main is linked into the
resulting executable, and thus considered to be loaded by the
bootstrap class loader. However, it really makes more sense for this
code to be loaded by the system class loader.
This fixes the problem by adding a new option to gcj. With this
option we can now tell the difference between classes which should be
"loaded" by the system loader and those which should be loaded by the
bootstrap loader. This adds two new ABI settings to indicate the use
of the "bootstrap loader" option. The default is to use the system
loader, and we now compile libgcj with the new -fbootstrap-classes
flag.
One question with this patch is what to do with classes that are
loaded via dlopen() (e.g. via the lib-x-y-z.so trick), and which are
compiled with the "system class loader" setting. This patch ignores
this setting for any classes other than those explicitly linked into
the executable.
I think this is the right thing to do, since it seems weird for a
class to show up in the "wrong" class loader. Also, consider the
scenario where the bootstrap loader decides to dlopen(lib-x-y-z.so),
and classes from this .so are registered with the system loader. What
this implies is that the current request would fail (since the
bootstrap loader would not find the class), but future requests that
go via the system loader would succeed... we could circumvent all
this, but it just seems like a mess.
Let me know what you think.
Tom
Index: gcc/java/ChangeLog
from Tom Tromey <tromey@redhat.com>
* gcj.texi (Code Generation): Document -fbootstrap-classes.
* decl.c (GCJ_BOOTSTRAP_LOADER_ADDITION): New macro.
(parse_version): Use it.
* lang.opt (-fbootstrap-classes): New option.
Index: libjava/ChangeLog
from Tom Tromey <tromey@redhat.com>
* external/w3c_dom/Makefile.in: Rebuilt.
* external/w3c_dom/Makefile.am (libw3c_gcj_la_GCJFLAGS): Added
-fbootstrap-classes.
* external/sax/Makefile.in: Rebuilt.
* external/sax/Makefile.am (libsax_gcj_la_GCJFLAGS): Added
-fbootstrap-classes.
* java/lang/Class.h (_Jv_CopyClassesToSystemLoader): Declare as
friend.
* java/lang/natVMClassLoader.cc (getSystemClassLoaderInternal):
Call _Jv_CopyClassesToSystemLoader.
* java/lang/natClassLoader.cc (system_class_list): New global.
(_Jv_RegisterClassHookDefault): Handle bootstrap and system
classes differently.
(_Jv_CopyClassesToSystemLoader): New function.
(SYSTEM_LOADER_INITIALIZED): New define.
* include/jvm.h (GCJ_BOOTSTRAP_LOADER_ADDITION): New define.
(_Jv_CheckABIVersion): Use it.
(_Jv_ClassForBootstrapLoader): New function.
* Makefile.in: Rebuilt.
* Makefile.am (AM_GCJFLAGS): Added -fbootstrap-classes.
Index: gcc/java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.219
diff -u -r1.219 decl.c
--- gcc/java/decl.c 29 Apr 2005 18:42:48 -0000 1.219
+++ gcc/java/decl.c 3 May 2005 20:52:21 -0000
@@ -64,6 +64,10 @@
/* Used when computing the ABI version. */
#define GCJ_BINARYCOMPAT_ADDITION 5
+/* Used when defining a class that should be loaded by the bootstrap
+ loader. */
+#define GCJ_BOOTSTRAP_LOADER_ADDITION 1
+
/* The version of the BC ABI that we generate. At the moment we are
compatible with what shipped in GCC 4.0. This must be kept in sync
with parse_version(), libgcj, and reality (if the BC format
@@ -620,6 +624,8 @@
probably always require strict matching for ordinary ABI. */
if (flag_indirect_dispatch)
abi_version = GCJ_CURRENT_BC_ABI_VERSION;
+ if (flag_bootstrap_classes)
+ abi_version += GCJ_BOOTSTRAP_LOADER_ADDITION;
gcj_abi_version = build_int_cstu (ptr_type_node, abi_version);
}
Index: gcc/java/gcj.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/gcj.texi,v
retrieving revision 1.83
diff -u -r1.83 gcj.texi
--- gcc/java/gcj.texi 27 Apr 2005 18:29:27 -0000 1.83
+++ gcc/java/gcj.texi 3 May 2005 20:52:22 -0000
@@ -512,6 +512,15 @@
However, if you compile CNI code with the standard ABI, you can call
it from code built with the binary compatibility ABI.
+@item -fbootstrap-classes
+This option can be use to tell @code{libgcj} that the compiled classes
+should be loaded by the bootstrap loader, not the system class loader.
+By default, if you compile a class and link it into an executable, it
+will be treated as if it was loaded using the system class loader.
+This is convenient, as it means that things like
+@code{Class.forName()} will search @samp{CLASSPATH} to find the
+desired class.
+
@end table
Index: gcc/java/lang.opt
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.opt,v
retrieving revision 1.15
diff -u -r1.15 lang.opt
--- gcc/java/lang.opt 3 May 2005 18:47:49 -0000 1.15
+++ gcc/java/lang.opt 3 May 2005 20:52:22 -0000
@@ -176,5 +176,9 @@
Java Var(flag_use_divide_subroutine) Init(1)
Call a library routine to do integer divisions
+fbootstrap-classes
+Java Var(flag_bootstrap_classes)
+Generated should be loaded by bootstrap loader
+
version
Java
Index: libjava/Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.482
diff -u -r1.482 Makefile.am
--- libjava/Makefile.am 29 Apr 2005 22:09:41 -0000 1.482
+++ libjava/Makefile.am 3 May 2005 20:52:31 -0000
@@ -204,7 +204,7 @@
@LIBGCJ_JAVAFLAGS@ \
-fclasspath= -fbootclasspath=$(BOOTCLASSPATH) \
--encoding=UTF-8 \
- -Wno-deprecated
+ -Wno-deprecated -fbootstrap-classes
if USING_GCC
AM_CFLAGS = @LIBGCJ_CFLAGS@ $(WARNINGS)
Index: libjava/external/sax/Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/external/sax/Makefile.am,v
retrieving revision 1.7
diff -u -r1.7 Makefile.am
--- libjava/external/sax/Makefile.am 29 Mar 2005 22:28:24 -0000 1.7
+++ libjava/external/sax/Makefile.am 3 May 2005 20:52:39 -0000
@@ -35,7 +35,7 @@
noinst_LTLIBRARIES = libsax-gcj.la
libsax_gcj_la_SOURCES = sax.jar
-libsax_gcj_la_GCJFLAGS = -findirect-dispatch $(AM_GCJFLAGS)
+libsax_gcj_la_GCJFLAGS = -findirect-dispatch -fbootstrap-classes $(AM_GCJFLAGS)
source_files = \
org/xml/sax/SAXNotSupportedException.java \
Index: libjava/external/w3c_dom/Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/external/w3c_dom/Makefile.am,v
retrieving revision 1.7
diff -u -r1.7 Makefile.am
--- libjava/external/w3c_dom/Makefile.am 29 Mar 2005 22:28:25 -0000 1.7
+++ libjava/external/w3c_dom/Makefile.am 3 May 2005 20:52:39 -0000
@@ -35,7 +35,7 @@
noinst_LTLIBRARIES = libw3c-gcj.la
libw3c_gcj_la_SOURCES = w3c.jar
-libw3c_gcj_la_GCJFLAGS = -findirect-dispatch $(AM_GCJFLAGS)
+libw3c_gcj_la_GCJFLAGS = -findirect-dispatch -fbootstrap-classes $(AM_GCJFLAGS)
source_files = \
org/w3c/dom/xpath/XPathNamespace.java \
Index: libjava/include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.84
diff -u -r1.84 jvm.h
--- libjava/include/jvm.h 29 Apr 2005 18:35:36 -0000 1.84
+++ libjava/include/jvm.h 3 May 2005 20:52:40 -0000
@@ -565,6 +565,7 @@
// This is used to find ABI versions we recognize.
#define GCJ_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 10)
#define GCJ_BINARYCOMPAT_ADDITION 5
+#define GCJ_BOOTSTRAP_LOADER_ADDITION 1
// At present we know we are compatible with the BC ABI as used in GCC
// 4.0.
@@ -573,10 +574,18 @@
inline bool
_Jv_CheckABIVersion (unsigned long value)
{
- // Recognize our defined C++ ABI.
+ // Recognize our defined C++ ABIs.
return (value == GCJ_VERSION
- // At the moment this is the only BC ABI we recognize.
- || value == GCJ_40_BC_ABI_VERSION);
+ || value == (GCJ_VERSION + GCJ_BOOTSTRAP_LOADER_ADDITION)
+ || value == GCJ_40_BC_ABI_VERSION
+ || value == (GCJ_40_BC_ABI_VERSION + GCJ_BOOTSTRAP_LOADER_ADDITION));
+}
+
+inline bool
+_Jv_ClassForBootstrapLoader (unsigned long value)
+{
+ return (value == (GCJ_VERSION + GCJ_BOOTSTRAP_LOADER_ADDITION)
+ || value == (GCJ_40_BC_ABI_VERSION + GCJ_BOOTSTRAP_LOADER_ADDITION));
}
// It makes the source cleaner if we simply always define this
Index: libjava/java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.h,v
retrieving revision 1.82
diff -u -r1.82 Class.h
--- libjava/java/lang/Class.h 29 Apr 2005 20:02:47 -0000 1.82
+++ libjava/java/lang/Class.h 3 May 2005 20:52:41 -0000
@@ -236,6 +236,8 @@
jboolean _Jv_IsInterpretedClass (jclass);
+void _Jv_CopyClassesToSystemLoader (java::lang::ClassLoader *);
+
#ifdef INTERPRETER
void _Jv_InitField (jobject, jclass, int);
@@ -494,6 +496,8 @@
friend void *::_Jv_ResolvePoolEntry (jclass this_class, jint index);
+ friend void ::_Jv_CopyClassesToSystemLoader (java::lang::ClassLoader *);
+
// Chain for class pool. This also doubles as the ABI version
// number. It is only used for this purpose at class registration
// time, and only for precompiled classes.
Index: libjava/java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.81
diff -u -r1.81 natClassLoader.cc
--- libjava/java/lang/natClassLoader.cc 6 Apr 2005 22:30:01 -0000 1.81
+++ libjava/java/lang/natClassLoader.cc 3 May 2005 20:52:41 -0000
@@ -52,6 +52,15 @@
static jclass loaded_classes[HASH_LEN];
+// This records classes which will be registered with the system class
+// loader when it is initialized.
+static jclass system_class_list;
+
+// This is used as the value of system_class_list after we have
+// initialized the system class loader; it lets us know that we should
+// no longer pay attention to the system abi flag.
+#define SYSTEM_LOADER_INITIALIZED ((jclass) -1)
+
// This is the root of a linked list of classes
static jclass stack_head;
@@ -165,6 +174,22 @@
void
_Jv_RegisterClassHookDefault (jclass klass)
{
+ // This is bogus, but there doesn't seem to be a better place to do
+ // it.
+ if (! klass->engine)
+ klass->engine = &_Jv_soleCompiledEngine;
+
+ if (system_class_list != SYSTEM_LOADER_INITIALIZED)
+ {
+ unsigned long abi = (unsigned long) klass->next_or_version;
+ if (! _Jv_ClassForBootstrapLoader (abi))
+ {
+ klass->next_or_version = system_class_list;
+ system_class_list = klass;
+ return;
+ }
+ }
+
jint hash = HASH_UTF (klass->name);
// If the class is already registered, don't re-register it.
@@ -193,9 +218,6 @@
}
}
- // FIXME: this is really bogus!
- if (! klass->engine)
- klass->engine = &_Jv_soleCompiledEngine;
klass->next_or_version = loaded_classes[hash];
loaded_classes[hash] = klass;
}
@@ -216,6 +238,21 @@
_Jv_RegisterClasses (classes);
}
+// This is used during initialization to register all compiled-in
+// classes that are not part of the core with the system class loader.
+void
+_Jv_CopyClassesToSystemLoader (java::lang::ClassLoader *loader)
+{
+ for (jclass klass = system_class_list;
+ klass;
+ klass = klass->next_or_version)
+ {
+ klass->loader = loader;
+ loader->loadedClasses->put(klass->name->toString(), klass);
+ }
+ system_class_list = SYSTEM_LOADER_INITIALIZED;
+}
+
jclass
_Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
{
Index: libjava/java/lang/natVMClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natVMClassLoader.cc,v
retrieving revision 1.12
diff -u -r1.12 natVMClassLoader.cc
--- libjava/java/lang/natVMClassLoader.cc 21 Apr 2005 17:20:36 -0000 1.12
+++ libjava/java/lang/natVMClassLoader.cc 3 May 2005 20:52:41 -0000
@@ -99,6 +99,7 @@
java::lang::VMClassLoader::getSystemClassLoaderInternal()
{
_Jv_InitClass (&gnu::gcj::runtime::ExtensionClassLoader::class$);
+ _Jv_CopyClassesToSystemLoader (gnu::gcj::runtime::ExtensionClassLoader::system_instance);
return gnu::gcj::runtime::ExtensionClassLoader::system_instance;
}