mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
5f5f0635f1
commit
2599b56f41
|
|
@ -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>
|
2008-03-10 Jim Meyering <meyering@redhat.com>
|
||||||
|
|
||||||
Don't leak upon failed realloc.
|
Don't leak upon failed realloc.
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,6 +1,6 @@
|
||||||
// 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:
|
||||||
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,
|
||||||
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:
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* 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;
|
||||||
|
|
||||||
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;
|
||||||
|
|
@ -129,6 +130,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.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// 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. */
|
||||||
#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)
|
||||||
// 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)
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue