7082263: Reflection::resolve_field/field_get/field_set are broken

Reviewed-by: kvn, dholmes, stefank, coleenp
This commit is contained in:
Tom Rodriguez 2011-08-30 00:54:09 -07:00
parent e3342531b4
commit cebdce4479
15 changed files with 6 additions and 1025 deletions

View file

@ -4020,249 +4020,6 @@ JVM_END
#endif
//---------------------------------------------------------------------------
//
// Support for old native code-based reflection (pre-JDK 1.4)
// Disabled by default in the product build.
//
// See reflection.hpp for information on SUPPORT_OLD_REFLECTION
//
//---------------------------------------------------------------------------
#ifdef SUPPORT_OLD_REFLECTION
JVM_ENTRY(jobjectArray, JVM_GetClassFields(JNIEnv *env, jclass cls, jint which))
JVMWrapper("JVM_GetClassFields");
JvmtiVMObjectAllocEventCollector oam;
oop mirror = JNIHandles::resolve_non_null(cls);
objArrayOop result = Reflection::reflect_fields(mirror, which, CHECK_NULL);
return (jobjectArray) JNIHandles::make_local(env, result);
JVM_END
JVM_ENTRY(jobjectArray, JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which))
JVMWrapper("JVM_GetClassMethods");
JvmtiVMObjectAllocEventCollector oam;
oop mirror = JNIHandles::resolve_non_null(cls);
objArrayOop result = Reflection::reflect_methods(mirror, which, CHECK_NULL);
//%note jvm_r4
return (jobjectArray) JNIHandles::make_local(env, result);
JVM_END
JVM_ENTRY(jobjectArray, JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which))
JVMWrapper("JVM_GetClassConstructors");
JvmtiVMObjectAllocEventCollector oam;
oop mirror = JNIHandles::resolve_non_null(cls);
objArrayOop result = Reflection::reflect_constructors(mirror, which, CHECK_NULL);
//%note jvm_r4
return (jobjectArray) JNIHandles::make_local(env, result);
JVM_END
JVM_ENTRY(jobject, JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which))
JVMWrapper("JVM_GetClassField");
JvmtiVMObjectAllocEventCollector oam;
if (name == NULL) return NULL;
Handle str (THREAD, JNIHandles::resolve_non_null(name));
const char* cstr = java_lang_String::as_utf8_string(str());
TempNewSymbol field_name = SymbolTable::probe(cstr, (int)strlen(cstr));
if (field_name == NULL) {
THROW_0(vmSymbols::java_lang_NoSuchFieldException());
}
oop mirror = JNIHandles::resolve_non_null(cls);
oop result = Reflection::reflect_field(mirror, field_name, which, CHECK_NULL);
if (result == NULL) {
THROW_0(vmSymbols::java_lang_NoSuchFieldException());
}
return JNIHandles::make_local(env, result);
JVM_END
JVM_ENTRY(jobject, JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which))
JVMWrapper("JVM_GetClassMethod");
JvmtiVMObjectAllocEventCollector oam;
if (name == NULL) {
THROW_0(vmSymbols::java_lang_NullPointerException());
}
Handle str (THREAD, JNIHandles::resolve_non_null(name));
const char* cstr = java_lang_String::as_utf8_string(str());
TempNewSymbol method_name = SymbolTable::probe(cstr, (int)strlen(cstr));
if (method_name == NULL) {
THROW_0(vmSymbols::java_lang_NoSuchMethodException());
}
oop mirror = JNIHandles::resolve_non_null(cls);
objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types)));
oop result = Reflection::reflect_method(mirror, method_name, tarray,
which, CHECK_NULL);
if (result == NULL) {
THROW_0(vmSymbols::java_lang_NoSuchMethodException());
}
return JNIHandles::make_local(env, result);
JVM_END
JVM_ENTRY(jobject, JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which))
JVMWrapper("JVM_GetClassConstructor");
JvmtiVMObjectAllocEventCollector oam;
oop mirror = JNIHandles::resolve_non_null(cls);
objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types)));
oop result = Reflection::reflect_constructor(mirror, tarray, which, CHECK_NULL);
if (result == NULL) {
THROW_0(vmSymbols::java_lang_NoSuchMethodException());
}
return (jobject) JNIHandles::make_local(env, result);
JVM_END
// Instantiation ///////////////////////////////////////////////////////////////////////////////
JVM_ENTRY(jobject, JVM_NewInstance(JNIEnv *env, jclass cls))
JVMWrapper("JVM_NewInstance");
Handle mirror(THREAD, JNIHandles::resolve_non_null(cls));
methodOop resolved_constructor = java_lang_Class::resolved_constructor(mirror());
if (resolved_constructor == NULL) {
klassOop k = java_lang_Class::as_klassOop(mirror());
// The java.lang.Class object caches a resolved constructor if all the checks
// below were done successfully and a constructor was found.
// Do class based checks
if (java_lang_Class::is_primitive(mirror())) {
const char* msg = "";
if (mirror == Universe::bool_mirror()) msg = "java/lang/Boolean";
else if (mirror == Universe::char_mirror()) msg = "java/lang/Character";
else if (mirror == Universe::float_mirror()) msg = "java/lang/Float";
else if (mirror == Universe::double_mirror()) msg = "java/lang/Double";
else if (mirror == Universe::byte_mirror()) msg = "java/lang/Byte";
else if (mirror == Universe::short_mirror()) msg = "java/lang/Short";
else if (mirror == Universe::int_mirror()) msg = "java/lang/Integer";
else if (mirror == Universe::long_mirror()) msg = "java/lang/Long";
THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), msg);
}
// Check whether we are allowed to instantiate this class
Klass::cast(k)->check_valid_for_instantiation(false, CHECK_NULL); // Array classes get caught here
instanceKlassHandle klass(THREAD, k);
// Make sure class is initialized (also so all methods are rewritten)
klass->initialize(CHECK_NULL);
// Lookup default constructor
resolved_constructor = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature());
if (resolved_constructor == NULL) {
ResourceMark rm(THREAD);
THROW_MSG_0(vmSymbols::java_lang_InstantiationException(), klass->external_name());
}
// Cache result in java.lang.Class object. Does not have to be MT safe.
java_lang_Class::set_resolved_constructor(mirror(), resolved_constructor);
}
assert(resolved_constructor != NULL, "sanity check");
methodHandle constructor = methodHandle(THREAD, resolved_constructor);
// We have an initialized instanceKlass with a default constructor
instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)));
assert(klass->is_initialized() || klass->is_being_initialized(), "sanity check");
// Do security check
klassOop caller_klass = NULL;
if (UsePrivilegedStack) {
caller_klass = thread->security_get_caller_class(2);
if (!Reflection::verify_class_access(caller_klass, klass(), false) ||
!Reflection::verify_field_access(caller_klass,
klass(),
klass(),
constructor->access_flags(),
false,
true)) {
ResourceMark rm(THREAD);
THROW_MSG_0(vmSymbols::java_lang_IllegalAccessException(), klass->external_name());
}
}
// Allocate object and call constructor
Handle receiver = klass->allocate_instance_handle(CHECK_NULL);
JavaCalls::call_default_constructor(thread, constructor, receiver, CHECK_NULL);
jobject res = JNIHandles::make_local(env, receiver());
if (JvmtiExport::should_post_vm_object_alloc()) {
JvmtiExport::post_vm_object_alloc(JavaThread::current(), receiver());
}
return res;
JVM_END
// Field ////////////////////////////////////////////////////////////////////////////////////////////
JVM_ENTRY(jobject, JVM_GetField(JNIEnv *env, jobject field, jobject obj))
JVMWrapper("JVM_GetField");
JvmtiVMObjectAllocEventCollector oam;
Handle field_mirror(thread, JNIHandles::resolve(field));
Handle receiver (thread, JNIHandles::resolve(obj));
fieldDescriptor fd;
Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_NULL);
jvalue value;
BasicType type = Reflection::field_get(&value, &fd, receiver);
oop box = Reflection::box(&value, type, CHECK_NULL);
return JNIHandles::make_local(env, box);
JVM_END
JVM_ENTRY(jvalue, JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode))
JVMWrapper("JVM_GetPrimitiveField");
Handle field_mirror(thread, JNIHandles::resolve(field));
Handle receiver (thread, JNIHandles::resolve(obj));
fieldDescriptor fd;
jvalue value;
value.j = 0;
Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_(value));
BasicType type = Reflection::field_get(&value, &fd, receiver);
BasicType wide_type = (BasicType) wCode;
if (type != wide_type) {
Reflection::widen(&value, type, wide_type, CHECK_(value));
}
return value;
JVM_END // should really be JVM_END, but that doesn't work for union types!
JVM_ENTRY(void, JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val))
JVMWrapper("JVM_SetField");
Handle field_mirror(thread, JNIHandles::resolve(field));
Handle receiver (thread, JNIHandles::resolve(obj));
oop box = JNIHandles::resolve(val);
fieldDescriptor fd;
Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK);
BasicType field_type = fd.field_type();
jvalue value;
BasicType value_type;
if (field_type == T_OBJECT || field_type == T_ARRAY) {
// Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array
value_type = Reflection::unbox_for_regular_object(box, &value);
Reflection::field_set(&value, &fd, receiver, field_type, CHECK);
} else {
value_type = Reflection::unbox_for_primitive(box, &value, CHECK);
Reflection::field_set(&value, &fd, receiver, value_type, CHECK);
}
JVM_END
JVM_ENTRY(void, JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, unsigned char vCode))
JVMWrapper("JVM_SetPrimitiveField");
Handle field_mirror(thread, JNIHandles::resolve(field));
Handle receiver (thread, JNIHandles::resolve(obj));
fieldDescriptor fd;
Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK);
BasicType value_type = (BasicType) vCode;
Reflection::field_set(&v, &fd, receiver, value_type, CHECK);
JVM_END
// Method ///////////////////////////////////////////////////////////////////////////////////////////
JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
@ -4302,8 +4059,6 @@ JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjec
return res;
JVM_END
#endif /* SUPPORT_OLD_REFLECTION */
// Atomic ///////////////////////////////////////////////////////////////////////////////////////////
JVM_LEAF(jboolean, JVM_SupportsCX8())