natClassLoader.cc (_Jv_RegisterInitiatingLoader): Check loading constraints.
authorTom Tromey <tromey@redhat.com>
Thu, 13 Mar 2008 16:43:54 +0000 (16:43 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Thu, 13 Mar 2008 16:43:54 +0000 (16:43 +0000)
* 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

libjava/ChangeLog
libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class
libjava/classpath/lib/java/lang/ClassLoader.class
libjava/include/jvm.h
libjava/java/lang/ClassLoader.h
libjava/java/lang/ClassLoader.java
libjava/java/lang/natClassLoader.cc
libjava/link.cc

index 84ea6c0b3be285bac5054a7dc9b4a948fb1afbf6..bd92959477bb78ee5e7b92ecb660c225d3416d59 100644 (file)
@@ -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.
index 03de2da433497001e6c4ba1c6614d303d34d6d47..02b44fe24aec5140d6befa45950951e6af53e733 100644 (file)
Binary files a/libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class and b/libjava/classpath/lib/java/lang/ClassLoader$AnnotationsKey.class differ
index ef012c299db1e647ee073dfda6ed4a6a1cab071b..694b514cc98be32d6bf989b6d8a22b36bff871cb 100644 (file)
Binary files a/libjava/classpath/lib/java/lang/ClassLoader.class and b/libjava/classpath/lib/java/lang/ClassLoader.class differ
index 84847548f01b7ff71646f426a7e3d496aabcc971..64cd6b5d7f9ad47c5d515f47b39df67bf531d30b 100644 (file)
@@ -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__));
 
index ed6f5449adcec78611dbe02464a374e5deacce68..5112eab983e1e7c2b157b0de8a08743b93c3c5e9 100644 (file)
@@ -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;
index 4682dbbf01049c4523e513aabf6315eb4e22f4c6..e0463ac2af6bcac83cf04c9c401bc1112da484ab 100644 (file)
@@ -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;
@@ -129,6 +130,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.
index 9a687ff9105b893b2d136d5055e106ac9dfa9157..fac1e4dede0c0ccdfc3616d4337def3ca7e3daf4 100644 (file)
@@ -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.
 //
index d6fd2ddafbda745544a4573f0a0a768b63583885..f995531e813ecf73ac16e600107307bb87fd37fb 100644 (file)
@@ -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);
+               }
            }
        }