aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2008-03-13 16:43:54 +0000
committerTom Tromey <tromey@gcc.gnu.org>2008-03-13 16:43:54 +0000
commit2599b56f41927c9122e457bb811dc89a10164d2b (patch)
tree3e00c86cfe961bb8b754069406dbd928045c1a31
parent5f5f0635f1921f40de45c6783fe0c4e9b4c0d1ba (diff)
downloadgcc-2599b56f41927c9122e457bb811dc89a10164d2b.zip
gcc-2599b56f41927c9122e457bb811dc89a10164d2b.tar.gz
gcc-2599b56f41927c9122e457bb811dc89a10164d2b.tar.bz2
natClassLoader.cc (_Jv_RegisterInitiatingLoader): Check loading constraints.
* java/lang/natClassLoader.cc (_Jv_RegisterInitiatingLoader): Check loading constraints. (_Jv_CheckOrCreateLoadingConstraint): New function. * java/lang/ClassLoader.java (loadingConstraints): New field. * link.cc (_Jv_Linker::find_field): Use _Jv_CheckOrCreateLoadingConstraint. (_Jv_Linker::check_loading_constraints): New function. (_Jv_Linker::resolve_method_entry): Use check_loading_constraints. (_Jv_Linker::append_partial_itable): Likewise. (_Jv_Linker::layout_vtable_methods): Likewise. * include/jvm.h (_Jv_Linker::check_loading_constraints): Declare. (_Jv_CheckOrCreateLoadingConstraint): Declare. From-SVN: r133172
-rw-r--r--libjava/ChangeLog16
-rw-r--r--libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.classbin1160 -> 1160 bytes
-rw-r--r--libjava/classpath/lib/java/lang/ClassLoader.classbin12507 -> 12663 bytes
-rw-r--r--libjava/include/jvm.h6
-rw-r--r--libjava/java/lang/ClassLoader.h1
-rw-r--r--libjava/java/lang/ClassLoader.java12
-rw-r--r--libjava/java/lang/natClassLoader.cc59
-rw-r--r--libjava/link.cc73
8 files changed, 123 insertions, 44 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 84ea6c0..bd92959 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,19 @@
+2008-03-13 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/natClassLoader.cc (_Jv_RegisterInitiatingLoader):
+ Check loading constraints.
+ (_Jv_CheckOrCreateLoadingConstraint): New function.
+ * java/lang/ClassLoader.java (loadingConstraints): New field.
+ * link.cc (_Jv_Linker::find_field): Use
+ _Jv_CheckOrCreateLoadingConstraint.
+ (_Jv_Linker::check_loading_constraints): New function.
+ (_Jv_Linker::resolve_method_entry): Use
+ check_loading_constraints.
+ (_Jv_Linker::append_partial_itable): Likewise.
+ (_Jv_Linker::layout_vtable_methods): Likewise.
+ * include/jvm.h (_Jv_Linker::check_loading_constraints): Declare.
+ (_Jv_CheckOrCreateLoadingConstraint): Declare.
+
2008-03-10 Jim Meyering <meyering@redhat.com>
Don't leak upon failed realloc.
diff --git a/libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class b/libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class
index 03de2da..02b44fe 100644
--- a/libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class
+++ b/libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class
Binary files differ
diff --git a/libjava/classpath/lib/java/lang/ClassLoader.class b/libjava/classpath/lib/java/lang/ClassLoader.class
index ef012c2..694b514 100644
--- a/libjava/classpath/lib/java/lang/ClassLoader.class
+++ b/libjava/classpath/lib/java/lang/ClassLoader.class
Binary files differ
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 8484754..64cd6b5 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -1,6 +1,6 @@
// jvm.h - Header file for private implementation information. -*- c++ -*-
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation
This file is part of libgcj.
@@ -265,6 +265,7 @@ private:
jclass, jclass *);
static _Jv_Field *find_field(jclass, jclass, jclass *, _Jv_Utf8Const *,
_Jv_Utf8Const *);
+ static void check_loading_constraints (_Jv_Method *, jclass, jclass);
static void prepare_constant_time_tables(jclass);
static jshort get_interfaces(jclass, _Jv_ifaces *);
static void link_symbol_table(jclass);
@@ -557,6 +558,9 @@ extern void _Jv_CallAnyMethodA (jobject obj,
jboolean is_jni_call = true,
jclass iface = NULL);
+extern void _Jv_CheckOrCreateLoadingConstraint (jclass,
+ java::lang::ClassLoader *);
+
extern jobject _Jv_NewMultiArray (jclass, jint ndims, jint* dims)
__attribute__((__malloc__));
diff --git a/libjava/java/lang/ClassLoader.h b/libjava/java/lang/ClassLoader.h
index ed6f544..5112eab 100644
--- a/libjava/java/lang/ClassLoader.h
+++ b/libjava/java/lang/ClassLoader.h
@@ -86,6 +86,7 @@ private:
void checkInitialized();
public: // actually package-private
::java::util::HashMap * __attribute__((aligned(__alignof__( ::java::lang::Object)))) loadedClasses;
+ ::java::util::HashMap * loadingConstraints;
::java::util::HashMap * definedPackages;
private:
::java::lang::ClassLoader * parent;
diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java
index 4682dbb..e0463ac 100644
--- a/libjava/java/lang/ClassLoader.java
+++ b/libjava/java/lang/ClassLoader.java
@@ -1,5 +1,5 @@
/* ClassLoader.java -- responsible for loading classes into the VM
- Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -45,6 +45,7 @@ import gnu.java.util.EmptyEnumeration;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.ref.WeakReference;
import java.net.URL;
import java.nio.ByteBuffer;
import java.security.CodeSource;
@@ -130,6 +131,15 @@ public abstract class ClassLoader
final HashMap loadedClasses = new HashMap();
/**
+ * Loading constraints registered with this classloader. This maps
+ * a class name to a weak reference to a class. When the reference
+ * is non-null, it means that a reference to the name must resolve
+ * to the indicated class.
+ */
+ final HashMap<String, WeakReference<Class>> loadingConstraints
+ = new HashMap<String, WeakReference<Class>>();
+
+ /**
* All packages defined by this classloader. It is not private in order to
* allow native code (and trusted subclasses) access to this field.
*/
diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc
index 9a687ff..fac1e4d 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, 2005, 2006 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008 Free Software Foundation
This file is part of libgcj.
@@ -41,6 +41,7 @@ details. */
#include <java/lang/StringBuffer.h>
#include <java/io/Serializable.h>
#include <java/lang/Cloneable.h>
+#include <java/lang/ref/WeakReference.h>
#include <java/util/HashMap.h>
#include <gnu/gcj/runtime/BootClassLoader.h>
#include <gnu/gcj/runtime/SystemClassLoader.h>
@@ -143,7 +144,21 @@ _Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
// them later.
return;
}
- loader->loadedClasses->put(klass->name->toString(), klass);
+
+ JvSynchronize sync (loader->loadingConstraints);
+
+ using namespace java::lang::ref;
+
+ jstring name = klass->getName();
+ WeakReference *ref = (WeakReference *) loader->loadingConstraints->get (name);
+ if (ref)
+ {
+ jclass constraint = (jclass) ref->get();
+ if (constraint && constraint != klass)
+ throw new java::lang::LinkageError(JvNewStringLatin1("loading constraint violated"));
+ }
+ loader->loadingConstraints->put(name, new WeakReference(klass));
+ loader->loadedClasses->put(name, klass);
}
// If we found an error while defining an interpreted class, we must
@@ -156,6 +171,46 @@ _Jv_UnregisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
loader->loadedClasses->remove(klass->name->toString());
}
+// Check a loading constraint. In particular check that, if there is
+// a constraint for the name of KLASS in LOADER, that it maps to
+// KLASS. If there is no such constraint, make a new one. If the
+// constraint is violated, throw an exception. Do nothing for
+// primitive types.
+void
+_Jv_CheckOrCreateLoadingConstraint (jclass klass,
+ java::lang::ClassLoader *loader)
+{
+ // Strip arrays.
+ while (klass->isArray())
+ klass = klass->getComponentType();
+ // Ignore primitive types.
+ if (klass->isPrimitive())
+ return;
+
+ if (! loader)
+ loader = java::lang::VMClassLoader::bootLoader;
+ jstring name = klass->getName();
+
+ JvSynchronize sync (loader->loadingConstraints);
+
+ using namespace java::lang::ref;
+
+ WeakReference *ref = (WeakReference *) loader->loadingConstraints->get (name);
+ if (ref)
+ {
+ jclass constraint = (jclass) ref->get();
+ if (constraint)
+ {
+ if (klass != constraint)
+ throw new java::lang::LinkageError(JvNewStringLatin1("loading constraint violated"));
+ // Otherwise, all is ok.
+ return;
+ }
+ }
+ // No constraint (or old constraint GC'd). Make a new one.
+ loader->loadingConstraints->put(name, new WeakReference(klass));
+}
+
// Class registration.
//
diff --git a/libjava/link.cc b/libjava/link.cc
index d6fd2dd..f995531 100644
--- a/libjava/link.cc
+++ b/libjava/link.cc
@@ -246,13 +246,9 @@ _Jv_Linker::find_field (jclass klass, jclass owner,
if (_Jv_CheckAccess (klass, *found_class, the_field->flags))
{
// Note that the field returned by find_field_helper is always
- // resolved. There's no point checking class loaders here,
- // since we already did the work to look up all the types.
- // FIXME: being lazy here would be nice.
- if (the_field->type != field_type)
- throw new java::lang::LinkageError
- (JvNewStringLatin1
- ("field type mismatch with different loaders"));
+ // resolved. However, we still use the constraint mechanism
+ // because this may affect other lookups.
+ _Jv_CheckOrCreateLoadingConstraint (klass, (*found_class)->loader);
}
else
{
@@ -269,6 +265,23 @@ _Jv_Linker::find_field (jclass klass, jclass owner,
return the_field;
}
+// Check loading constraints for method.
+void
+_Jv_Linker::check_loading_constraints (_Jv_Method *method, jclass self_class,
+ jclass other_class)
+{
+ JArray<jclass> *klass_args;
+ jclass klass_return;
+
+ _Jv_GetTypesFromSignature (method, self_class, &klass_args, &klass_return);
+ jclass *klass_arg = elements (klass_args);
+ java::lang::ClassLoader *found_loader = other_class->loader;
+
+ _Jv_CheckOrCreateLoadingConstraint (klass_return, found_loader);
+ for (int i = 0; i < klass_args->length; i++)
+ _Jv_CheckOrCreateLoadingConstraint (*(klass_arg++), found_loader);
+}
+
_Jv_Method *
_Jv_Linker::resolve_method_entry (jclass klass, jclass &found_class,
int class_index, int name_and_type_index,
@@ -359,39 +372,10 @@ _Jv_Linker::resolve_method_entry (jclass klass, jclass &found_class,
throw new java::lang::NoSuchMethodError (sb->toString());
}
- // if (found_class->loader != klass->loader), then we
- // must actually check that the types of arguments
- // correspond. That is, for each argument type, and
- // the return type, doing _Jv_FindClassFromSignature
- // with either loader should produce the same result,
- // i.e., exactly the same jclass object. JVMS 5.4.3.3
+ // if (found_class->loader != klass->loader), then we must actually
+ // check that the types of arguments correspond. JVMS 5.4.3.3.
if (found_class->loader != klass->loader)
- {
- JArray<jclass> *found_args, *klass_args;
- jclass found_return, klass_return;
-
- _Jv_GetTypesFromSignature (the_method,
- found_class,
- &found_args,
- &found_return);
- _Jv_GetTypesFromSignature (the_method,
- klass,
- &klass_args,
- &klass_return);
-
- jclass *found_arg = elements (found_args);
- jclass *klass_arg = elements (klass_args);
-
- for (int i = 0; i < found_args->length; i++)
- {
- if (*(found_arg++) != *(klass_arg++))
- throw new java::lang::LinkageError (JvNewStringLatin1
- ("argument type mismatch with different loaders"));
- }
- if (found_return != klass_return)
- throw new java::lang::LinkageError (JvNewStringLatin1
- ("return type mismatch with different loaders"));
- }
+ check_loading_constraints (the_method, klass, found_class);
return the_method;
}
@@ -925,7 +909,8 @@ _Jv_Linker::append_partial_itable (jclass klass, jclass iface,
continue;
meth = NULL;
- for (jclass cl = klass; cl; cl = cl->getSuperclass())
+ jclass cl;
+ for (cl = klass; cl; cl = cl->getSuperclass())
{
meth = _Jv_GetMethodLocal (cl, iface->methods[j].name,
iface->methods[j].signature);
@@ -947,6 +932,9 @@ _Jv_Linker::append_partial_itable (jclass klass, jclass iface,
itable[pos] = (void *) &_Jv_ThrowAbstractMethodError;
else
itable[pos] = meth->ncode;
+
+ if (cl->loader != iface->loader)
+ check_loading_constraints (meth, cl, iface);
}
else
{
@@ -1501,6 +1489,11 @@ _Jv_Linker::layout_vtable_methods (jclass klass)
sb->append(_Jv_GetMethodString(declarer, super_meth));
throw new VerifyError(sb->toString());
}
+ else if (declarer->loader != klass->loader)
+ {
+ // JVMS 5.4.2.
+ check_loading_constraints (meth, klass, declarer);
+ }
}
}