summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libjava/ChangeLog34
-rw-r--r--libjava/defineclass.cc4
-rw-r--r--libjava/gnu/gcj/runtime/VMClassLoader.java23
-rw-r--r--libjava/gnu/gcj/runtime/natVMClassLoader.cc12
-rw-r--r--libjava/include/jvm.h2
-rw-r--r--libjava/java/lang/Class.h8
-rw-r--r--libjava/java/lang/Package.java9
-rw-r--r--libjava/java/lang/VMClassLoader.java36
-rw-r--r--libjava/java/lang/natClassLoader.cc126
-rw-r--r--libjava/java/lang/natVMClassLoader.cc7
-rw-r--r--libjava/prims.cc4
11 files changed, 159 insertions, 106 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 17f4d64cf22..a1b28a63546 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,5 +1,39 @@
2005-01-10 Tom Tromey <tromey@redhat.com>
+ PR libgcj/12016, PR libgcj/18405, PR libgcj/17738:
+ * java/lang/Package.java (getPackages): Use VMClassLoader when
+ appropriate.
+ (getPackage): Likewise.
+ * prims.cc (_Jv_CreateJavaVM): Call
+ _Jv_RegisterBootstrapPackages.
+ * include/jvm.h (_Jv_RegisterBootstrapPackages): Declare.
+ * java/lang/VMClassLoader.java (getPackage): Rewrote.
+ (getPackages): Likewise.
+ (definedPackages): New field.
+ (definePackageForNative): New method.
+ * java/lang/Class.h (_Jv_FindClassInCache): Updated.
+ * java/lang/natVMClassLoader.cc (loadClass): Updated.
+ * defineclass.cc (handleClassBegin): Use
+ ClassLoader.findLoadedClass.
+ * java/lang/natClassLoader.cc (_Jv_RegisterInitiatingLoader):
+ Rewrote.
+ (struct _Jv_LoaderInfo): Removed.
+ (initiated_classes): Likewise.
+ (_Jv_UnregisterClass): Don't use initiated_classes.
+ (_Jv_FindClassInCache): Likewise. Removed 'loader' argument.
+ (_Jv_FindClass): Register classes found during boostrap.
+ (BOOTSTRAP_CLASS_LIST_SIZE): New define.
+ (bootstrap_class_list): New global.
+ (bootstrap_index): Likewise.
+ (_Jv_RegisterBootstrapPackages): New function.
+ * gnu/gcj/runtime/natVMClassLoader.cc (findClass): Call
+ definePackageForNative.
+ (findClass): Updated.
+ * gnu/gcj/runtime/VMClassLoader.java (definePackageForNative):
+ New method.
+
+2005-01-10 Tom Tromey <tromey@redhat.com>
+
PR libgcj/18868:
* include/jvm.h (_Jv_Linker::find_field): Declare.
(_Jv_Linker::find_field_helper): Likewise.
diff --git a/libjava/defineclass.cc b/libjava/defineclass.cc
index 1a0c4e4da60..a40bff1758e 100644
--- a/libjava/defineclass.cc
+++ b/libjava/defineclass.cc
@@ -1,6 +1,6 @@
// defineclass.cc - defining a class from .class format.
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of libgcj.
@@ -868,7 +868,7 @@ _Jv_ClassReader::handleClassBegin (int access_flags, int this_class, int super_c
// was ClassLoader.defineClass called with an expected class name?
if (def->name == 0)
{
- jclass orig = _Jv_FindClassInCache (loadedName, def->loader);
+ jclass orig = def->loader->findLoadedClass(loadedName->toString());
if (orig == 0)
{
diff --git a/libjava/gnu/gcj/runtime/VMClassLoader.java b/libjava/gnu/gcj/runtime/VMClassLoader.java
index f9ef872b30a..2d46ebcb770 100644
--- a/libjava/gnu/gcj/runtime/VMClassLoader.java
+++ b/libjava/gnu/gcj/runtime/VMClassLoader.java
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation
+/* Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of libgcj.
@@ -118,6 +118,27 @@ public final class VMClassLoader extends java.net.URLClassLoader
instance.init();
}
+ // Define a package for something loaded natively.
+ void definePackageForNative(String className)
+ {
+ int lastDot = className.lastIndexOf('.');
+ if (lastDot != -1)
+ {
+ String packageName = className.substring(0, lastDot);
+ if (getPackage(packageName) == null)
+ {
+ // FIXME: this assumes we're defining the core, which
+ // isn't necessarily so. We could detect this and set up
+ // appropriately. We could also look at a manifest file
+ // compiled into the .so.
+ definePackage(packageName, "Java Platform API Specification",
+ "GNU", "1.4", "gcj", "GNU",
+ null, // FIXME: gcj version.
+ null);
+ }
+ }
+ }
+
// This keeps track of shared libraries we've already tried to load.
private HashSet tried_libraries = new HashSet();
diff --git a/libjava/gnu/gcj/runtime/natVMClassLoader.cc b/libjava/gnu/gcj/runtime/natVMClassLoader.cc
index 42ac2a02107..7f2ee34eb32 100644
--- a/libjava/gnu/gcj/runtime/natVMClassLoader.cc
+++ b/libjava/gnu/gcj/runtime/natVMClassLoader.cc
@@ -1,6 +1,6 @@
// Native code for VMClassLoader
-/* Copyright (C) 2002, 2003 Free Software Foundation
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation
This file is part of libgcj.
@@ -24,7 +24,7 @@ jclass
gnu::gcj::runtime::VMClassLoader::findClass (jstring name)
{
_Jv_Utf8Const *name_u = _Jv_makeUtf8Const (name);
- jclass klass = _Jv_FindClassInCache (name_u, 0);
+ jclass klass = _Jv_FindClassInCache (name_u);
if (! klass && lib_control != LIB_NEVER)
{
@@ -65,12 +65,14 @@ gnu::gcj::runtime::VMClassLoader::findClass (jstring name)
so_base_name = so_base_name->substring (0, nd);
if (loaded)
- klass = _Jv_FindClassInCache (name_u, 0);
+ klass = _Jv_FindClassInCache (name_u);
}
}
- // Now try loading using the interpreter.
- if (! klass)
+ // Either define the package, or try loading using the interpreter.
+ if (klass)
+ definePackageForNative(name);
+ else
klass = java::net::URLClassLoader::findClass (name);
return klass;
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 52471bfac9a..d45ef25b699 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -561,4 +561,6 @@ extern void (*_Jv_JVMPI_Notify_THREAD_END) (JVMPI_Event *event);
/* FIXME: this should really be defined in some more generic place */
#define ROUND(V, A) (((((unsigned) (V))-1) | ((A)-1))+1)
+extern void _Jv_RegisterBootstrapPackages ();
+
#endif /* __JAVA_JVM_H__ */
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index f38f16f680e..cea1c13a8e2 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -1,6 +1,6 @@
// Class.h - Header file for java.lang.Class. -*- c++ -*-
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of libgcj.
@@ -215,8 +215,7 @@ void _Jv_RegisterInitiatingLoader (jclass,java::lang::ClassLoader*);
void _Jv_UnregisterClass (jclass);
jclass _Jv_FindClass (_Jv_Utf8Const *name,
java::lang::ClassLoader *loader);
-jclass _Jv_FindClassInCache (_Jv_Utf8Const *name,
- java::lang::ClassLoader *loader);
+jclass _Jv_FindClassInCache (_Jv_Utf8Const *name);
jclass _Jv_PopClass (void);
void _Jv_PushClass (jclass k);
void _Jv_NewArrayClass (jclass element,
@@ -440,8 +439,7 @@ private:
friend void ::_Jv_UnregisterClass (jclass);
friend jclass (::_Jv_FindClass) (_Jv_Utf8Const *name,
java::lang::ClassLoader *loader);
- friend jclass (::_Jv_FindClassInCache) (_Jv_Utf8Const *name,
- java::lang::ClassLoader *loader);
+ friend jclass (::_Jv_FindClassInCache) (_Jv_Utf8Const *name);
friend jclass (::_Jv_PopClass) (void);
friend void ::_Jv_PushClass (jclass k);
friend void ::_Jv_NewArrayClass (jclass element,
diff --git a/libjava/java/lang/Package.java b/libjava/java/lang/Package.java
index 89945cadd8a..29b42b63cf1 100644
--- a/libjava/java/lang/Package.java
+++ b/libjava/java/lang/Package.java
@@ -1,5 +1,5 @@
/* Package.java -- information about a package
- Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -274,7 +274,7 @@ public class Package
{
// Get the caller's classloader
ClassLoader cl = VMSecurityManager.currentClassLoader();
- return cl != null ? cl.getPackage(name) : null;
+ return cl != null ? cl.getPackage(name) : VMClassLoader.getPackage(name);
}
/**
@@ -288,10 +288,7 @@ public class Package
// Get the caller's classloader
Class c = VMSecurityManager.getClassContext()[1];
ClassLoader cl = c.getClassLoader();
- // Sun's implementation returns the packages loaded by the bootstrap
- // classloader if cl is null, but right now our bootstrap classloader
- // does not create any Packages.
- return cl != null ? cl.getPackages() : new Package[0];
+ return cl != null ? cl.getPackages() : VMClassLoader.getPackages();
}
/**
diff --git a/libjava/java/lang/VMClassLoader.java b/libjava/java/lang/VMClassLoader.java
index 8f78f9bb666..1afda4570ea 100644
--- a/libjava/java/lang/VMClassLoader.java
+++ b/libjava/java/lang/VMClassLoader.java
@@ -1,6 +1,6 @@
/* VMClassLoader.java -- Reference implementation of native interface
required by ClassLoader
- Copyright (C) 1998, 2001, 2002, 2003, 2004 Free Software Foundation
+ Copyright (C) 1998, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of GNU Classpath.
@@ -76,6 +76,8 @@ final class VMClassLoader
unknownProtectionDomain = new ProtectionDomain(null, permissions);
}
+ static final HashMap definedPackages = new HashMap();
+
/**
* Helper to define a class using a string of bytes. This assumes that
* the security checks have already been performed, if necessary.
@@ -173,9 +175,9 @@ final class VMClassLoader
* @param name the name to find
* @return the named package, if it exists
*/
- static Package getPackage(String name)
+ static synchronized Package getPackage(String name)
{
- return null;
+ return (Package) definedPackages.get(name);
}
/**
@@ -185,9 +187,33 @@ final class VMClassLoader
*
* @return all named packages, if any exist
*/
- static Package[] getPackages()
+ static synchronized Package[] getPackages()
+ {
+ Package[] packages = new Package[definedPackages.size()];
+ return (Package[]) definedPackages.values().toArray(packages);
+ }
+
+ // Define a package for something loaded natively.
+ static synchronized void definePackageForNative(String className)
{
- return new Package[0];
+ int lastDot = className.lastIndexOf('.');
+ if (lastDot != -1)
+ {
+ String packageName = className.substring(0, lastDot);
+ if (getPackage(packageName) == null)
+ {
+ // FIXME: this assumes we're defining the core, which
+ // isn't necessarily so. We could detect this and set up
+ // appropriately. We could also look at a manifest file
+ // compiled into the .so.
+ Package p = new Package(packageName,
+ "Java Platform API Specification",
+ "GNU", "1.4", "gcj", "GNU",
+ null, // FIXME: gcj version.
+ null);
+ definedPackages.put(packageName, p);
+ }
+ }
}
/**
diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc
index f6571bd66ba..b05c1dd0a5b 100644
--- a/libjava/java/lang/natClassLoader.cc
+++ b/libjava/java/lang/natClassLoader.cc
@@ -1,6 +1,6 @@
// natClassLoader.cc - Implementation of java.lang.ClassLoader native methods.
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of libgcj.
@@ -42,19 +42,7 @@ details. */
#include <java/lang/StringBuffer.h>
#include <java/io/Serializable.h>
#include <java/lang/Cloneable.h>
-
-//
-// A single class can have many "initiating" class loaders,
-// and a single "defining" class loader. The Defining
-// class loader is what is returned from Class.getClassLoader()
-// and is used when loading dependent classes during resolution.
-// The set of initiating class loaders are used to ensure
-// safety of linking, and is maintained in the hash table
-// "initiated_classes". A defining classloader is by definition also
-// initiating, so we only store classes in this table if they have more
-// than one class loader associated.
-//
-
+#include <java/util/HashMap.h>
// Size of local hash table.
#define HASH_LEN 1013
@@ -62,56 +50,37 @@ details. */
// Hash function for Utf8Consts.
#define HASH_UTF(Utf) ((Utf)->hash16() % HASH_LEN)
-struct _Jv_LoaderInfo
-{
- _Jv_LoaderInfo *next;
- java::lang::Class *klass;
- java::lang::ClassLoader *loader;
-};
-
-static _Jv_LoaderInfo *initiated_classes[HASH_LEN];
static jclass loaded_classes[HASH_LEN];
// This is the root of a linked list of classes
static jclass stack_head;
+// While bootstrapping we keep a list of classes we found, so that we
+// can register their packages. There aren't many of these so we
+// just keep a small buffer here and abort if we overflow.
+#define BOOTSTRAP_CLASS_LIST_SIZE 20
+static jclass bootstrap_class_list[BOOTSTRAP_CLASS_LIST_SIZE];
+static int bootstrap_index;
+
+// This tries to find a class in our built-in cache. This cache is
+// used only for classes which are linked in to the executable or
+// loaded via dlopen().
jclass
-_Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
+_Jv_FindClassInCache (_Jv_Utf8Const *name)
{
JvSynchronize sync (&java::lang::Class::class$);
jint hash = HASH_UTF (name);
- if (loader && loader == java::lang::ClassLoader::getSystemClassLoader())
- loader = NULL;
-
- // first, if LOADER is a defining loader, then it is also initiating
jclass klass;
for (klass = loaded_classes[hash]; klass; klass = klass->next)
{
- if (loader == klass->loader && _Jv_equalUtf8Consts (name, klass->name))
+ if (_Jv_equalUtf8Consts (name, klass->name))
break;
}
- // otherwise, it may be that the class in question was defined
- // by some other loader, but that the loading was initiated by
- // the loader in question.
- if (!klass)
- {
- _Jv_LoaderInfo *info;
- for (info = initiated_classes[hash]; info; info = info->next)
- {
- if (loader == info->loader
- && _Jv_equalUtf8Consts (name, info->klass->name))
- {
- klass = info->klass;
- break;
- }
- }
- }
-
return klass;
}
@@ -130,38 +99,15 @@ _Jv_UnregisterClass (jclass the_class)
break;
}
}
-
- _Jv_LoaderInfo **info = &(initiated_classes[hash]);
- for ( ; ; info = &((*info)->next))
- {
- while (*info && (*info)->klass == the_class)
- {
- _Jv_LoaderInfo *old = *info;
- *info = (*info)->next;
- _Jv_Free (old);
- }
-
- if (*info == NULL)
- break;
- }
}
+// Register an initiating class loader for a given class.
void
_Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
{
- if (loader && loader == java::lang::ClassLoader::getSystemClassLoader())
- loader = NULL;
-
- // This information can't be visible to the GC.
- _Jv_LoaderInfo *info
- = (_Jv_LoaderInfo *) _Jv_Malloc (sizeof(_Jv_LoaderInfo));
- jint hash = HASH_UTF(klass->name);
-
- JvSynchronize sync (&java::lang::Class::class$);
- info->loader = loader;
- info->klass = klass;
- info->next = initiated_classes[hash];
- initiated_classes[hash] = info;
+ if (! loader)
+ loader = java::lang::ClassLoader::getSystemClassLoader();
+ loader->loadedClasses->put(klass->name->toString(), klass);
}
// This function is called many times during startup, before main() is
@@ -254,15 +200,21 @@ _Jv_RegisterClass (jclass klass)
jclass
_Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
{
- jclass klass = _Jv_FindClassInCache (name, loader);
+ // See if the class was already loaded by this loader. This handles
+ // initiating loader checks, as we register classes with their
+ // initiating loaders.
+ java::lang::ClassLoader *sys
+ = java::lang::ClassLoader::getSystemClassLoader ();
+ java::lang::ClassLoader *real = loader;
+ if (! real)
+ real = sys;
+ jstring sname = name->toString();
+ // We might still be bootstrapping the VM, in which case there
+ // won't be a system class loader yet.
+ jclass klass = real ? real->findLoadedClass (sname) : NULL;
if (! klass)
{
- jstring sname = name->toString();
-
- java::lang::ClassLoader *sys
- = java::lang::ClassLoader::getSystemClassLoader ();
-
if (loader)
{
// Load using a user-defined loader, jvmspec 5.3.2
@@ -277,7 +229,7 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
if (klass && klass->getClassLoaderInternal () != delegate)
_Jv_RegisterInitiatingLoader (klass, loader);
}
- else
+ else if (sys)
{
// Load using the bootstrap loader jvmspec 5.3.1.
klass = sys->loadClass (sname, false);
@@ -286,6 +238,15 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
if (klass)
_Jv_RegisterInitiatingLoader (klass, 0);
}
+ else
+ {
+ // Not even a bootstrap loader, try the built-in cache.
+ klass = _Jv_FindClassInCache (name);
+
+ if (bootstrap_index == BOOTSTRAP_CLASS_LIST_SIZE)
+ abort ();
+ bootstrap_class_list[bootstrap_index++] = klass;
+ }
}
else
{
@@ -297,6 +258,13 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
return klass;
}
+void
+_Jv_RegisterBootstrapPackages ()
+{
+ for (int i = 0; i < bootstrap_index; ++i)
+ java::lang::VMClassLoader::definePackageForNative(bootstrap_class_list[i]->getName());
+}
+
jclass
_Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
java::lang::ClassLoader *loader)
diff --git a/libjava/java/lang/natVMClassLoader.cc b/libjava/java/lang/natVMClassLoader.cc
index 841b3e0789e..e34be99296d 100644
--- a/libjava/java/lang/natVMClassLoader.cc
+++ b/libjava/java/lang/natVMClassLoader.cc
@@ -1,6 +1,6 @@
// natVMClassLoader.cc - VMClassLoader native methods
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of libgcj.
@@ -130,7 +130,7 @@ jclass
java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve)
{
_Jv_Utf8Const *utf = _Jv_makeUtf8Const (name);
- jclass klass = _Jv_FindClassInCache (utf, NULL);
+ jclass klass = _Jv_FindClassInCache (utf);
if (klass)
{
// We never want to return a class without its supers linked.
@@ -140,6 +140,9 @@ java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve)
_Jv_InitClass (klass);
else
_Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
+
+ definePackageForNative(name);
}
+
return klass;
}
diff --git a/libjava/prims.cc b/libjava/prims.cc
index e3d5750cd1c..ac48d0dd9e3 100644
--- a/libjava/prims.cc
+++ b/libjava/prims.cc
@@ -1,6 +1,6 @@
// prims.cc - Code for core of runtime environment.
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of libgcj.
@@ -968,6 +968,8 @@ _Jv_CreateJavaVM (void* /*vm_args*/)
// system loader, by having it read the class path.
gnu::gcj::runtime::VMClassLoader::initialize();
+ _Jv_RegisterBootstrapPackages();
+
no_memory = new java::lang::OutOfMemoryError;
java::lang::VMThrowable::trace_enabled = 1;