Commit 2599b56f by Tom Tromey Committed by Tom Tromey

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
parent 5f5f0635
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> 2008-03-10 Jim Meyering <meyering@redhat.com>
Don't leak upon failed realloc. Don't leak upon failed realloc.
......
// jvm.h - Header file for private implementation information. -*- c++ -*- // 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. This file is part of libgcj.
...@@ -265,6 +265,7 @@ private: ...@@ -265,6 +265,7 @@ private:
jclass, jclass *); jclass, jclass *);
static _Jv_Field *find_field(jclass, jclass, jclass *, _Jv_Utf8Const *, static _Jv_Field *find_field(jclass, jclass, jclass *, _Jv_Utf8Const *,
_Jv_Utf8Const *); _Jv_Utf8Const *);
static void check_loading_constraints (_Jv_Method *, jclass, jclass);
static void prepare_constant_time_tables(jclass); static void prepare_constant_time_tables(jclass);
static jshort get_interfaces(jclass, _Jv_ifaces *); static jshort get_interfaces(jclass, _Jv_ifaces *);
static void link_symbol_table(jclass); static void link_symbol_table(jclass);
...@@ -557,6 +558,9 @@ extern void _Jv_CallAnyMethodA (jobject obj, ...@@ -557,6 +558,9 @@ extern void _Jv_CallAnyMethodA (jobject obj,
jboolean is_jni_call = true, jboolean is_jni_call = true,
jclass iface = NULL); jclass iface = NULL);
extern void _Jv_CheckOrCreateLoadingConstraint (jclass,
java::lang::ClassLoader *);
extern jobject _Jv_NewMultiArray (jclass, jint ndims, jint* dims) extern jobject _Jv_NewMultiArray (jclass, jint ndims, jint* dims)
__attribute__((__malloc__)); __attribute__((__malloc__));
......
...@@ -86,6 +86,7 @@ private: ...@@ -86,6 +86,7 @@ private:
void checkInitialized(); void checkInitialized();
public: // actually package-private public: // actually package-private
::java::util::HashMap * __attribute__((aligned(__alignof__( ::java::lang::Object)))) loadedClasses; ::java::util::HashMap * __attribute__((aligned(__alignof__( ::java::lang::Object)))) loadedClasses;
::java::util::HashMap * loadingConstraints;
::java::util::HashMap * definedPackages; ::java::util::HashMap * definedPackages;
private: private:
::java::lang::ClassLoader * parent; ::java::lang::ClassLoader * parent;
......
/* ClassLoader.java -- responsible for loading classes into the VM /* 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. This file is part of GNU Classpath.
...@@ -45,6 +45,7 @@ import gnu.java.util.EmptyEnumeration; ...@@ -45,6 +45,7 @@ import gnu.java.util.EmptyEnumeration;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.URL; import java.net.URL;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.CodeSource; import java.security.CodeSource;
...@@ -130,6 +131,15 @@ public abstract class ClassLoader ...@@ -130,6 +131,15 @@ public abstract class ClassLoader
final HashMap loadedClasses = new HashMap(); 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 * All packages defined by this classloader. It is not private in order to
* allow native code (and trusted subclasses) access to this field. * allow native code (and trusted subclasses) access to this field.
*/ */
......
// natClassLoader.cc - Implementation of java.lang.ClassLoader native methods. // 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. This file is part of libgcj.
...@@ -41,6 +41,7 @@ details. */ ...@@ -41,6 +41,7 @@ details. */
#include <java/lang/StringBuffer.h> #include <java/lang/StringBuffer.h>
#include <java/io/Serializable.h> #include <java/io/Serializable.h>
#include <java/lang/Cloneable.h> #include <java/lang/Cloneable.h>
#include <java/lang/ref/WeakReference.h>
#include <java/util/HashMap.h> #include <java/util/HashMap.h>
#include <gnu/gcj/runtime/BootClassLoader.h> #include <gnu/gcj/runtime/BootClassLoader.h>
#include <gnu/gcj/runtime/SystemClassLoader.h> #include <gnu/gcj/runtime/SystemClassLoader.h>
...@@ -143,7 +144,21 @@ _Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader) ...@@ -143,7 +144,21 @@ _Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
// them later. // them later.
return; 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 // If we found an error while defining an interpreted class, we must
...@@ -156,6 +171,46 @@ _Jv_UnregisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader) ...@@ -156,6 +171,46 @@ _Jv_UnregisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
loader->loadedClasses->remove(klass->name->toString()); 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. // Class registration.
// //
......
...@@ -246,13 +246,9 @@ _Jv_Linker::find_field (jclass klass, jclass owner, ...@@ -246,13 +246,9 @@ _Jv_Linker::find_field (jclass klass, jclass owner,
if (_Jv_CheckAccess (klass, *found_class, the_field->flags)) if (_Jv_CheckAccess (klass, *found_class, the_field->flags))
{ {
// Note that the field returned by find_field_helper is always // Note that the field returned by find_field_helper is always
// resolved. There's no point checking class loaders here, // resolved. However, we still use the constraint mechanism
// since we already did the work to look up all the types. // because this may affect other lookups.
// FIXME: being lazy here would be nice. _Jv_CheckOrCreateLoadingConstraint (klass, (*found_class)->loader);
if (the_field->type != field_type)
throw new java::lang::LinkageError
(JvNewStringLatin1
("field type mismatch with different loaders"));
} }
else else
{ {
...@@ -269,6 +265,23 @@ _Jv_Linker::find_field (jclass klass, jclass owner, ...@@ -269,6 +265,23 @@ _Jv_Linker::find_field (jclass klass, jclass owner,
return the_field; 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_Method *
_Jv_Linker::resolve_method_entry (jclass klass, jclass &found_class, _Jv_Linker::resolve_method_entry (jclass klass, jclass &found_class,
int class_index, int name_and_type_index, int class_index, int name_and_type_index,
...@@ -359,39 +372,10 @@ _Jv_Linker::resolve_method_entry (jclass klass, jclass &found_class, ...@@ -359,39 +372,10 @@ _Jv_Linker::resolve_method_entry (jclass klass, jclass &found_class,
throw new java::lang::NoSuchMethodError (sb->toString()); throw new java::lang::NoSuchMethodError (sb->toString());
} }
// if (found_class->loader != klass->loader), then we // if (found_class->loader != klass->loader), then we must actually
// must actually check that the types of arguments // check that the types of arguments correspond. JVMS 5.4.3.3.
// 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) if (found_class->loader != klass->loader)
{ check_loading_constraints (the_method, klass, found_class);
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"));
}
return the_method; return the_method;
} }
...@@ -925,7 +909,8 @@ _Jv_Linker::append_partial_itable (jclass klass, jclass iface, ...@@ -925,7 +909,8 @@ _Jv_Linker::append_partial_itable (jclass klass, jclass iface,
continue; continue;
meth = NULL; 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, meth = _Jv_GetMethodLocal (cl, iface->methods[j].name,
iface->methods[j].signature); iface->methods[j].signature);
...@@ -947,6 +932,9 @@ _Jv_Linker::append_partial_itable (jclass klass, jclass iface, ...@@ -947,6 +932,9 @@ _Jv_Linker::append_partial_itable (jclass klass, jclass iface,
itable[pos] = (void *) &_Jv_ThrowAbstractMethodError; itable[pos] = (void *) &_Jv_ThrowAbstractMethodError;
else else
itable[pos] = meth->ncode; itable[pos] = meth->ncode;
if (cl->loader != iface->loader)
check_loading_constraints (meth, cl, iface);
} }
else else
{ {
...@@ -1501,6 +1489,11 @@ _Jv_Linker::layout_vtable_methods (jclass klass) ...@@ -1501,6 +1489,11 @@ _Jv_Linker::layout_vtable_methods (jclass klass)
sb->append(_Jv_GetMethodString(declarer, super_meth)); sb->append(_Jv_GetMethodString(declarer, super_meth));
throw new VerifyError(sb->toString()); throw new VerifyError(sb->toString());
} }
else if (declarer->loader != klass->loader)
{
// JVMS 5.4.2.
check_loading_constraints (meth, klass, declarer);
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment