diff options
Diffstat (limited to 'libjava/java')
-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 |
3 files changed, 69 insertions, 3 deletions
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. // |