diff options
author | Tom Tromey <tromey@redhat.com> | 2008-03-13 16:43:54 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2008-03-13 16:43:54 +0000 |
commit | 2599b56f41927c9122e457bb811dc89a10164d2b (patch) | |
tree | 3e00c86cfe961bb8b754069406dbd928045c1a31 | |
parent | 5f5f0635f1921f40de45c6783fe0c4e9b4c0d1ba (diff) | |
download | gcc-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/ChangeLog | 16 | ||||
-rw-r--r-- | libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class | bin | 1160 -> 1160 bytes | |||
-rw-r--r-- | libjava/classpath/lib/java/lang/ClassLoader.class | bin | 12507 -> 12663 bytes | |||
-rw-r--r-- | libjava/include/jvm.h | 6 | ||||
-rw-r--r-- | libjava/java/lang/ClassLoader.h | 1 | ||||
-rw-r--r-- | libjava/java/lang/ClassLoader.java | 12 | ||||
-rw-r--r-- | libjava/java/lang/natClassLoader.cc | 59 | ||||
-rw-r--r-- | libjava/link.cc | 73 |
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 Binary files differindex 03de2da..02b44fe 100644 --- a/libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class +++ b/libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class diff --git a/libjava/classpath/lib/java/lang/ClassLoader.class b/libjava/classpath/lib/java/lang/ClassLoader.class Binary files differindex ef012c2..694b514 100644 --- a/libjava/classpath/lib/java/lang/ClassLoader.class +++ b/libjava/classpath/lib/java/lang/ClassLoader.class 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); + } } } |