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.

From-SVN: r93155
This commit is contained in:
Tom Tromey 2005-01-10 19:39:26 +00:00 committed by Tom Tromey
parent 2f2bc52472
commit 3fd8010046
11 changed files with 159 additions and 106 deletions

View File

@ -1,3 +1,37 @@
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:

View File

@ -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)
{

View File

@ -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();

View File

@ -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;

View File

@ -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__ */

View File

@ -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,

View File

@ -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();
}
/**

View File

@ -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()
{
return new Package[0];
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)
{
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);
}
}
}
/**

View File

@ -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)

View File

@ -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;
}

View File

@ -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;