aboutsummaryrefslogtreecommitdiff
path: root/libjava/java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java')
-rw-r--r--libjava/java/lang/ClassLoader.h1
-rw-r--r--libjava/java/lang/ClassLoader.java12
-rw-r--r--libjava/java/lang/natClassLoader.cc59
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.
//