natClassLoader.cc (defineClass0): Removed erroneous comment.
* java/lang/natClassLoader.cc (defineClass0): Removed erroneous comment. * java/lang/ClassLoader.java (defineClass): Use chained exception when rethrowing. * defineclass.cc (handleClassBegin): Mark class as interpreted. * java/lang/reflect/Modifier.java (INVISIBLE, INTERPRETED): New constants. * resolve.cc (_Jv_PrepareMissingMethods): New function. (_Jv_PrepareClass): Use it. * include/java-interp.h (_Jv_IsInterpretedClass): Rewrote. (_Jv_InterpClass): _Jv_PrepareMissingMethods now friend. * java/lang/Class.h (Class::getModifiers): Mask with ALL_FLAGS. (Class): _Jv_PrepareMissingMethods now friend. * java/lang/natClassLoader.cc (defineClass0): Use JvSynchronize. Record `NULL' for system class loader. (_Jv_RegisterInitiatingLoader): Use JvSynchronize. Special case system class loader. (_Jv_FindClassInCache): Likewise. (_Jv_UnregisterClass): Use JvSynchronize. Free old loader info. (_Jv_FindClass): Special case system class loader. * java/lang/natClass.cc (_Jv_abstractMethodError): New function. (_Jv_SetVTableEntries): Put _Jv_abstractMethodError into empty vtable slots. (_Jv_LayoutVTableMethods): Don't generate vtable slot for a method in a final class. (_getDeclaredMethod): Don't return synthetic methods. (getDeclaredMethods): Likewise. (_getMethod): Likewise. (_getMethods): Likewise. From-SVN: r60319
This commit is contained in:
parent
385405940e
commit
a1aba4f9a5
11 changed files with 221 additions and 96 deletions
|
@ -182,9 +182,9 @@ public:
|
|||
JArray<java::lang::reflect::Method *> *getMethods (void);
|
||||
|
||||
inline jint getModifiers (void)
|
||||
{
|
||||
return accflags;
|
||||
}
|
||||
{
|
||||
return accflags & java::lang::reflect::Modifier::ALL_FLAGS;
|
||||
}
|
||||
|
||||
jstring getName (void);
|
||||
|
||||
|
@ -348,6 +348,7 @@ private:
|
|||
_Jv_Utf8Const *method_signature);
|
||||
|
||||
friend void _Jv_PrepareClass (jclass);
|
||||
friend void _Jv_PrepareMissingMethods (jclass base, jclass iface_class);
|
||||
|
||||
friend class _Jv_ClassReader;
|
||||
friend class _Jv_InterpClass;
|
||||
|
|
|
@ -468,17 +468,18 @@ public abstract class ClassLoader
|
|||
{
|
||||
throw x; // rethrow
|
||||
}
|
||||
catch (java.lang.VirtualMachineError x)
|
||||
catch (VirtualMachineError x)
|
||||
{
|
||||
throw x; // rethrow
|
||||
}
|
||||
catch (java.lang.Throwable x)
|
||||
catch (Throwable x)
|
||||
{
|
||||
// This should never happen, or we are beyond spec.
|
||||
throw new InternalError ("Unexpected exception "
|
||||
+ "while defining class "
|
||||
+ name + ": "
|
||||
+ x.toString ());
|
||||
InternalError r = new InternalError ("Unexpected exception "
|
||||
+ "while defining class "
|
||||
+ name);
|
||||
r.initCause(x);
|
||||
throw r;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -343,7 +343,9 @@ java::lang::Class::_getDeclaredMethod (jstring name,
|
|||
while (--i >= 0)
|
||||
{
|
||||
if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
|
||||
&& _Jv_equaln (methods[i].signature, partial_sig, p_len))
|
||||
&& _Jv_equaln (methods[i].signature, partial_sig, p_len)
|
||||
&& (methods[i].accflags
|
||||
& java::lang::reflect::Modifier::INVISIBLE) == 0)
|
||||
{
|
||||
// Found it.
|
||||
using namespace java::lang::reflect;
|
||||
|
@ -368,7 +370,9 @@ java::lang::Class::getDeclaredMethods (void)
|
|||
if (method->name == NULL
|
||||
|| _Jv_equalUtf8Consts (method->name, clinit_name)
|
||||
|| _Jv_equalUtf8Consts (method->name, init_name)
|
||||
|| _Jv_equalUtf8Consts (method->name, finit_name))
|
||||
|| _Jv_equalUtf8Consts (method->name, finit_name)
|
||||
|| (methods[i].accflags
|
||||
& java::lang::reflect::Modifier::INVISIBLE) != 0)
|
||||
continue;
|
||||
numMethods++;
|
||||
}
|
||||
|
@ -382,7 +386,9 @@ java::lang::Class::getDeclaredMethods (void)
|
|||
if (method->name == NULL
|
||||
|| _Jv_equalUtf8Consts (method->name, clinit_name)
|
||||
|| _Jv_equalUtf8Consts (method->name, init_name)
|
||||
|| _Jv_equalUtf8Consts (method->name, finit_name))
|
||||
|| _Jv_equalUtf8Consts (method->name, finit_name)
|
||||
|| (methods[i].accflags
|
||||
& java::lang::reflect::Modifier::INVISIBLE) != 0)
|
||||
continue;
|
||||
java::lang::reflect::Method* rmethod
|
||||
= new java::lang::reflect::Method ();
|
||||
|
@ -514,7 +520,9 @@ java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
|
|||
{
|
||||
// FIXME: access checks.
|
||||
if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
|
||||
&& _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
|
||||
&& _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
|
||||
&& (klass->methods[i].accflags
|
||||
& java::lang::reflect::Modifier::INVISIBLE) == 0)
|
||||
{
|
||||
// Found it.
|
||||
using namespace java::lang::reflect;
|
||||
|
@ -565,7 +573,9 @@ java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
|
|||
if (method->name == NULL
|
||||
|| _Jv_equalUtf8Consts (method->name, clinit_name)
|
||||
|| _Jv_equalUtf8Consts (method->name, init_name)
|
||||
|| _Jv_equalUtf8Consts (method->name, finit_name))
|
||||
|| _Jv_equalUtf8Consts (method->name, finit_name)
|
||||
|| (method->accflags
|
||||
& java::lang::reflect::Modifier::INVISIBLE) != 0)
|
||||
continue;
|
||||
// Only want public methods.
|
||||
if (! java::lang::reflect::Modifier::isPublic (method->accflags))
|
||||
|
@ -1564,6 +1574,13 @@ isVirtualMethod (_Jv_Method *meth)
|
|||
&& meth->name->data[0] != '<');
|
||||
}
|
||||
|
||||
// This is put in empty vtable slots.
|
||||
static void
|
||||
_Jv_abstractMethodError (void)
|
||||
{
|
||||
throw new java::lang::AbstractMethodError();
|
||||
}
|
||||
|
||||
// Prepare virtual method declarations in KLASS, and any superclasses as
|
||||
// required, by determining their vtable index, setting method->index, and
|
||||
// finally setting the class's vtable_method_count. Must be called with the
|
||||
|
@ -1594,13 +1611,16 @@ _Jv_LayoutVTableMethods (jclass klass)
|
|||
continue;
|
||||
|
||||
if (superclass != NULL)
|
||||
super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name,
|
||||
meth->signature);
|
||||
{
|
||||
super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name,
|
||||
meth->signature);
|
||||
}
|
||||
|
||||
if (super_meth)
|
||||
meth->index = super_meth->index;
|
||||
else if (! (meth->accflags & java::lang::reflect::Modifier::FINAL))
|
||||
meth->index = index++;
|
||||
else if (! (meth->accflags & java::lang::reflect::Modifier::FINAL)
|
||||
&& ! (klass->accflags & java::lang::reflect::Modifier::FINAL))
|
||||
meth->index = index++;
|
||||
}
|
||||
|
||||
klass->vtable_method_count = index;
|
||||
|
@ -1626,8 +1646,7 @@ _Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable, jboolean *flags)
|
|||
continue;
|
||||
if ((meth->accflags & Modifier::ABSTRACT))
|
||||
{
|
||||
// FIXME: we should set abstract slots to a function that
|
||||
// throws AbstractMethodError. How can we do that on IA-64?
|
||||
vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError);
|
||||
flags[meth->index] = false;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -56,17 +56,18 @@ java::lang::ClassLoader::defineClass0 (jstring name,
|
|||
sizeof (_Jv_InterpClass));
|
||||
_Jv_InitNewClassFields (klass);
|
||||
|
||||
// synchronize on the class, so that it is not
|
||||
// attempted initialized until we're done loading.
|
||||
_Jv_MonitorEnter (klass);
|
||||
// Synchronize on the class, so that it is not attempted initialized
|
||||
// until we're done loading.
|
||||
JvSynchronize sync (klass);
|
||||
|
||||
// record which is the defining loader
|
||||
klass->loader = this;
|
||||
// Record the defining loader. For the system class loader, we
|
||||
// record NULL.
|
||||
if (this != java::lang::ClassLoader::getSystemClassLoader())
|
||||
klass->loader = this;
|
||||
|
||||
// register that we are the initiating loader...
|
||||
if (name != 0)
|
||||
{
|
||||
_Jv_Utf8Const * name2 = _Jv_makeUtf8Const (name);
|
||||
_Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
|
||||
|
||||
if (! _Jv_VerifyClassName (name2))
|
||||
throw new java::lang::ClassFormatError
|
||||
|
@ -86,16 +87,8 @@ java::lang::ClassLoader::defineClass0 (jstring name,
|
|||
|
||||
_Jv_UnregisterClass (klass);
|
||||
|
||||
_Jv_MonitorExit (klass);
|
||||
|
||||
// FIXME: Here we may want to test that EX does
|
||||
// indeed represent a valid exception. That is,
|
||||
// anything but ClassNotFoundException,
|
||||
// or some kind of Error.
|
||||
|
||||
// FIXME: Rewrite this as a cleanup instead of
|
||||
// as a catch handler.
|
||||
|
||||
// If EX is not a ClassNotFoundException, that's ok, because we
|
||||
// account for the possibility in defineClass().
|
||||
throw ex;
|
||||
}
|
||||
|
||||
|
@ -104,10 +97,6 @@ java::lang::ClassLoader::defineClass0 (jstring name,
|
|||
// if everything proceeded sucessfully, we're loaded.
|
||||
JvAssert (klass->state == JV_STATE_LOADED);
|
||||
|
||||
// if an exception is generated, this is initially missed.
|
||||
// however, we come back here in handleException0 below...
|
||||
_Jv_MonitorExit (klass);
|
||||
|
||||
return klass;
|
||||
|
||||
#else // INTERPRETER
|
||||
|
@ -293,10 +282,11 @@ _Jv_PrepareCompiledClass (jclass klass)
|
|||
// Hash function for Utf8Consts.
|
||||
#define HASH_UTF(Utf) (((Utf)->hash) % HASH_LEN)
|
||||
|
||||
struct _Jv_LoaderInfo {
|
||||
_Jv_LoaderInfo *next;
|
||||
java::lang::Class *klass;
|
||||
java::lang::ClassLoader *loader;
|
||||
struct _Jv_LoaderInfo
|
||||
{
|
||||
_Jv_LoaderInfo *next;
|
||||
java::lang::Class *klass;
|
||||
java::lang::ClassLoader *loader;
|
||||
};
|
||||
|
||||
static _Jv_LoaderInfo *initiated_classes[HASH_LEN];
|
||||
|
@ -309,9 +299,12 @@ static jclass loaded_classes[HASH_LEN];
|
|||
jclass
|
||||
_Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
|
||||
{
|
||||
_Jv_MonitorEnter (&java::lang::Class::class$);
|
||||
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)
|
||||
|
@ -337,15 +330,13 @@ _Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
|
|||
}
|
||||
}
|
||||
|
||||
_Jv_MonitorExit (&java::lang::Class::class$);
|
||||
|
||||
return klass;
|
||||
}
|
||||
|
||||
void
|
||||
_Jv_UnregisterClass (jclass the_class)
|
||||
{
|
||||
_Jv_MonitorEnter (&java::lang::Class::class$);
|
||||
JvSynchronize sync (&java::lang::Class::class$);
|
||||
jint hash = HASH_UTF(the_class->name);
|
||||
|
||||
jclass *klass = &(loaded_classes[hash]);
|
||||
|
@ -363,29 +354,32 @@ _Jv_UnregisterClass (jclass the_class)
|
|||
{
|
||||
while (*info && (*info)->klass == the_class)
|
||||
{
|
||||
_Jv_LoaderInfo *old = *info;
|
||||
*info = (*info)->next;
|
||||
_Jv_Free (old);
|
||||
}
|
||||
|
||||
if (*info == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
_Jv_MonitorExit (&java::lang::Class::class$);
|
||||
}
|
||||
|
||||
void
|
||||
_Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
|
||||
{
|
||||
// non-gc alloc!
|
||||
_Jv_LoaderInfo *info = (_Jv_LoaderInfo *) _Jv_Malloc (sizeof(_Jv_LoaderInfo));
|
||||
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);
|
||||
|
||||
_Jv_MonitorEnter (&java::lang::Class::class$);
|
||||
JvSynchronize sync (&java::lang::Class::class$);
|
||||
info->loader = loader;
|
||||
info->klass = klass;
|
||||
info->next = initiated_classes[hash];
|
||||
initiated_classes[hash] = info;
|
||||
_Jv_MonitorExit (&java::lang::Class::class$);
|
||||
}
|
||||
|
||||
// This function is called many times during startup, before main() is
|
||||
|
@ -471,6 +465,9 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
|
|||
{
|
||||
jstring sname = _Jv_NewStringUTF (name->data);
|
||||
|
||||
java::lang::ClassLoader *sys
|
||||
= java::lang::ClassLoader::getSystemClassLoader ();
|
||||
|
||||
if (loader)
|
||||
{
|
||||
// Load using a user-defined loader, jvmspec 5.3.2
|
||||
|
@ -479,14 +476,14 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
|
|||
// If "loader" delegated the loadClass operation to another
|
||||
// loader, explicitly register that it is also an initiating
|
||||
// loader of the given class.
|
||||
if (klass && (klass->getClassLoader () != loader))
|
||||
java::lang::ClassLoader *delegate = (loader == sys
|
||||
? NULL
|
||||
: loader);
|
||||
if (klass && klass->getClassLoaderInternal () != delegate)
|
||||
_Jv_RegisterInitiatingLoader (klass, loader);
|
||||
}
|
||||
else
|
||||
{
|
||||
java::lang::ClassLoader *sys
|
||||
= java::lang::ClassLoader::getSystemClassLoader ();
|
||||
|
||||
// Load using the bootstrap loader jvmspec 5.3.1.
|
||||
klass = sys->loadClass (sname, false);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* java.lang.reflect.Modifier
|
||||
Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -157,6 +157,17 @@ public class Modifier
|
|||
*/
|
||||
static final int ALL_FLAGS = 0xfff;
|
||||
|
||||
/**
|
||||
* GCJ-LOCAL: This access flag is set on methods we declare
|
||||
* internally but which must not be visible to reflection.
|
||||
*/
|
||||
static final int INVISIBLE = 0x1000;
|
||||
|
||||
/**
|
||||
* GCJ-LOCAL: This access flag is set on interpreted classes.
|
||||
*/
|
||||
static final int INTERPRETED = 0x1000;
|
||||
|
||||
/**
|
||||
* Check whether the given modifier is abstract.
|
||||
* @param mod the modifier.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue