aboutsummaryrefslogtreecommitdiff
path: root/libjava/java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java')
-rw-r--r--libjava/java/lang/Class.h7
-rw-r--r--libjava/java/lang/ClassLoader.java13
-rw-r--r--libjava/java/lang/natClass.cc41
-rw-r--r--libjava/java/lang/natClassLoader.cc75
-rw-r--r--libjava/java/lang/reflect/Modifier.java13
5 files changed, 89 insertions, 60 deletions
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index 4ccf388..d59899a 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -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;
diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java
index 033b2cc..8c99897 100644
--- a/libjava/java/lang/ClassLoader.java
+++ b/libjava/java/lang/ClassLoader.java
@@ -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;
}
}
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index bafac78..768ced6 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -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
diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc
index aeee08a..96a8181 100644
--- a/libjava/java/lang/natClassLoader.cc
+++ b/libjava/java/lang/natClassLoader.cc
@@ -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);
diff --git a/libjava/java/lang/reflect/Modifier.java b/libjava/java/lang/reflect/Modifier.java
index 75d0c9b..8171a88 100644
--- a/libjava/java/lang/reflect/Modifier.java
+++ b/libjava/java/lang/reflect/Modifier.java
@@ -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.
@@ -158,6 +158,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.
* @return <code>true</code> if abstract, <code>false</code> otherwise.