diff options
-rw-r--r-- | libjava/ChangeLog | 34 | ||||
-rw-r--r-- | libjava/defineclass.cc | 4 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/VMClassLoader.java | 23 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/natVMClassLoader.cc | 12 | ||||
-rw-r--r-- | libjava/include/jvm.h | 2 | ||||
-rw-r--r-- | libjava/java/lang/Class.h | 8 | ||||
-rw-r--r-- | libjava/java/lang/Package.java | 9 | ||||
-rw-r--r-- | libjava/java/lang/VMClassLoader.java | 36 | ||||
-rw-r--r-- | libjava/java/lang/natClassLoader.cc | 126 | ||||
-rw-r--r-- | libjava/java/lang/natVMClassLoader.cc | 7 | ||||
-rw-r--r-- | libjava/prims.cc | 4 |
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; |