comparison src/share/vm/prims/jvm.cpp @ 2729:19241ae0d839

7082263: Reflection::resolve_field/field_get/field_set are broken Reviewed-by: kvn, dholmes, stefank, coleenp
author never
date Tue, 30 Aug 2011 00:54:09 -0700
parents c7f3d0b4570f
children e6b1331a51d2
comparison
equal deleted inserted replaced
29:ed5f8be62b1e 30:0be17fb1c691
4018 4018
4019 4019
4020 #endif 4020 #endif
4021 4021
4022 4022
4023 //---------------------------------------------------------------------------
4024 //
4025 // Support for old native code-based reflection (pre-JDK 1.4)
4026 // Disabled by default in the product build.
4027 //
4028 // See reflection.hpp for information on SUPPORT_OLD_REFLECTION
4029 //
4030 //---------------------------------------------------------------------------
4031
4032 #ifdef SUPPORT_OLD_REFLECTION
4033
4034 JVM_ENTRY(jobjectArray, JVM_GetClassFields(JNIEnv *env, jclass cls, jint which))
4035 JVMWrapper("JVM_GetClassFields");
4036 JvmtiVMObjectAllocEventCollector oam;
4037 oop mirror = JNIHandles::resolve_non_null(cls);
4038 objArrayOop result = Reflection::reflect_fields(mirror, which, CHECK_NULL);
4039 return (jobjectArray) JNIHandles::make_local(env, result);
4040 JVM_END
4041
4042
4043 JVM_ENTRY(jobjectArray, JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which))
4044 JVMWrapper("JVM_GetClassMethods");
4045 JvmtiVMObjectAllocEventCollector oam;
4046 oop mirror = JNIHandles::resolve_non_null(cls);
4047 objArrayOop result = Reflection::reflect_methods(mirror, which, CHECK_NULL);
4048 //%note jvm_r4
4049 return (jobjectArray) JNIHandles::make_local(env, result);
4050 JVM_END
4051
4052
4053 JVM_ENTRY(jobjectArray, JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which))
4054 JVMWrapper("JVM_GetClassConstructors");
4055 JvmtiVMObjectAllocEventCollector oam;
4056 oop mirror = JNIHandles::resolve_non_null(cls);
4057 objArrayOop result = Reflection::reflect_constructors(mirror, which, CHECK_NULL);
4058 //%note jvm_r4
4059 return (jobjectArray) JNIHandles::make_local(env, result);
4060 JVM_END
4061
4062
4063 JVM_ENTRY(jobject, JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which))
4064 JVMWrapper("JVM_GetClassField");
4065 JvmtiVMObjectAllocEventCollector oam;
4066 if (name == NULL) return NULL;
4067 Handle str (THREAD, JNIHandles::resolve_non_null(name));
4068
4069 const char* cstr = java_lang_String::as_utf8_string(str());
4070 TempNewSymbol field_name = SymbolTable::probe(cstr, (int)strlen(cstr));
4071 if (field_name == NULL) {
4072 THROW_0(vmSymbols::java_lang_NoSuchFieldException());
4073 }
4074
4075 oop mirror = JNIHandles::resolve_non_null(cls);
4076 oop result = Reflection::reflect_field(mirror, field_name, which, CHECK_NULL);
4077 if (result == NULL) {
4078 THROW_0(vmSymbols::java_lang_NoSuchFieldException());
4079 }
4080 return JNIHandles::make_local(env, result);
4081 JVM_END
4082
4083
4084 JVM_ENTRY(jobject, JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which))
4085 JVMWrapper("JVM_GetClassMethod");
4086 JvmtiVMObjectAllocEventCollector oam;
4087 if (name == NULL) {
4088 THROW_0(vmSymbols::java_lang_NullPointerException());
4089 }
4090 Handle str (THREAD, JNIHandles::resolve_non_null(name));
4091
4092 const char* cstr = java_lang_String::as_utf8_string(str());
4093 TempNewSymbol method_name = SymbolTable::probe(cstr, (int)strlen(cstr));
4094 if (method_name == NULL) {
4095 THROW_0(vmSymbols::java_lang_NoSuchMethodException());
4096 }
4097
4098 oop mirror = JNIHandles::resolve_non_null(cls);
4099 objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types)));
4100 oop result = Reflection::reflect_method(mirror, method_name, tarray,
4101 which, CHECK_NULL);
4102 if (result == NULL) {
4103 THROW_0(vmSymbols::java_lang_NoSuchMethodException());
4104 }
4105 return JNIHandles::make_local(env, result);
4106 JVM_END
4107
4108
4109 JVM_ENTRY(jobject, JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which))
4110 JVMWrapper("JVM_GetClassConstructor");
4111 JvmtiVMObjectAllocEventCollector oam;
4112 oop mirror = JNIHandles::resolve_non_null(cls);
4113 objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types)));
4114 oop result = Reflection::reflect_constructor(mirror, tarray, which, CHECK_NULL);
4115 if (result == NULL) {
4116 THROW_0(vmSymbols::java_lang_NoSuchMethodException());
4117 }
4118 return (jobject) JNIHandles::make_local(env, result);
4119 JVM_END
4120
4121
4122 // Instantiation ///////////////////////////////////////////////////////////////////////////////
4123
4124 JVM_ENTRY(jobject, JVM_NewInstance(JNIEnv *env, jclass cls))
4125 JVMWrapper("JVM_NewInstance");
4126 Handle mirror(THREAD, JNIHandles::resolve_non_null(cls));
4127
4128 methodOop resolved_constructor = java_lang_Class::resolved_constructor(mirror());
4129 if (resolved_constructor == NULL) {
4130 klassOop k = java_lang_Class::as_klassOop(mirror());
4131 // The java.lang.Class object caches a resolved constructor if all the checks
4132 // below were done successfully and a constructor was found.
4133
4134 // Do class based checks
4135 if (java_lang_Class::is_primitive(mirror())) {
4136 const char* msg = "";
4137 if (mirror == Universe::bool_mirror()) msg = "java/lang/Boolean";
4138 else if (mirror == Universe::char_mirror()) msg = "java/lang/Character";
4139 else if (mirror == Universe::float_mirror()) msg = "java/lang/Float";
4140 else if (mirror == Universe::double_mirror()) msg = "java/lang/Double";
4141 else if (mirror == Universe::byte_mirror()) msg = "java/lang/Byte";
4142 else if (mirror == Universe::short_mirror()) msg = "java/lang/Short";
4143 else if (mirror == Universe::int_mirror()) msg = "java/lang/Integer";
4144 else if (mirror == Universe::long_mirror()) msg = "java/lang/Long";
4145 THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), msg);
4146 }
4147
4148 // Check whether we are allowed to instantiate this class
4149 Klass::cast(k)->check_valid_for_instantiation(false, CHECK_NULL); // Array classes get caught here
4150 instanceKlassHandle klass(THREAD, k);
4151 // Make sure class is initialized (also so all methods are rewritten)
4152 klass->initialize(CHECK_NULL);
4153
4154 // Lookup default constructor
4155 resolved_constructor = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature());
4156 if (resolved_constructor == NULL) {
4157 ResourceMark rm(THREAD);
4158 THROW_MSG_0(vmSymbols::java_lang_InstantiationException(), klass->external_name());
4159 }
4160
4161 // Cache result in java.lang.Class object. Does not have to be MT safe.
4162 java_lang_Class::set_resolved_constructor(mirror(), resolved_constructor);
4163 }
4164
4165 assert(resolved_constructor != NULL, "sanity check");
4166 methodHandle constructor = methodHandle(THREAD, resolved_constructor);
4167
4168 // We have an initialized instanceKlass with a default constructor
4169 instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)));
4170 assert(klass->is_initialized() || klass->is_being_initialized(), "sanity check");
4171
4172 // Do security check
4173 klassOop caller_klass = NULL;
4174 if (UsePrivilegedStack) {
4175 caller_klass = thread->security_get_caller_class(2);
4176
4177 if (!Reflection::verify_class_access(caller_klass, klass(), false) ||
4178 !Reflection::verify_field_access(caller_klass,
4179 klass(),
4180 klass(),
4181 constructor->access_flags(),
4182 false,
4183 true)) {
4184 ResourceMark rm(THREAD);
4185 THROW_MSG_0(vmSymbols::java_lang_IllegalAccessException(), klass->external_name());
4186 }
4187 }
4188
4189 // Allocate object and call constructor
4190 Handle receiver = klass->allocate_instance_handle(CHECK_NULL);
4191 JavaCalls::call_default_constructor(thread, constructor, receiver, CHECK_NULL);
4192
4193 jobject res = JNIHandles::make_local(env, receiver());
4194 if (JvmtiExport::should_post_vm_object_alloc()) {
4195 JvmtiExport::post_vm_object_alloc(JavaThread::current(), receiver());
4196 }
4197 return res;
4198 JVM_END
4199
4200
4201 // Field ////////////////////////////////////////////////////////////////////////////////////////////
4202
4203 JVM_ENTRY(jobject, JVM_GetField(JNIEnv *env, jobject field, jobject obj))
4204 JVMWrapper("JVM_GetField");
4205 JvmtiVMObjectAllocEventCollector oam;
4206 Handle field_mirror(thread, JNIHandles::resolve(field));
4207 Handle receiver (thread, JNIHandles::resolve(obj));
4208 fieldDescriptor fd;
4209 Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_NULL);
4210 jvalue value;
4211 BasicType type = Reflection::field_get(&value, &fd, receiver);
4212 oop box = Reflection::box(&value, type, CHECK_NULL);
4213 return JNIHandles::make_local(env, box);
4214 JVM_END
4215
4216
4217 JVM_ENTRY(jvalue, JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode))
4218 JVMWrapper("JVM_GetPrimitiveField");
4219 Handle field_mirror(thread, JNIHandles::resolve(field));
4220 Handle receiver (thread, JNIHandles::resolve(obj));
4221 fieldDescriptor fd;
4222 jvalue value;
4223 value.j = 0;
4224 Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_(value));
4225 BasicType type = Reflection::field_get(&value, &fd, receiver);
4226 BasicType wide_type = (BasicType) wCode;
4227 if (type != wide_type) {
4228 Reflection::widen(&value, type, wide_type, CHECK_(value));
4229 }
4230 return value;
4231 JVM_END // should really be JVM_END, but that doesn't work for union types!
4232
4233
4234 JVM_ENTRY(void, JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val))
4235 JVMWrapper("JVM_SetField");
4236 Handle field_mirror(thread, JNIHandles::resolve(field));
4237 Handle receiver (thread, JNIHandles::resolve(obj));
4238 oop box = JNIHandles::resolve(val);
4239 fieldDescriptor fd;
4240 Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK);
4241 BasicType field_type = fd.field_type();
4242 jvalue value;
4243 BasicType value_type;
4244 if (field_type == T_OBJECT || field_type == T_ARRAY) {
4245 // Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array
4246 value_type = Reflection::unbox_for_regular_object(box, &value);
4247 Reflection::field_set(&value, &fd, receiver, field_type, CHECK);
4248 } else {
4249 value_type = Reflection::unbox_for_primitive(box, &value, CHECK);
4250 Reflection::field_set(&value, &fd, receiver, value_type, CHECK);
4251 }
4252 JVM_END
4253
4254
4255 JVM_ENTRY(void, JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, unsigned char vCode))
4256 JVMWrapper("JVM_SetPrimitiveField");
4257 Handle field_mirror(thread, JNIHandles::resolve(field));
4258 Handle receiver (thread, JNIHandles::resolve(obj));
4259 fieldDescriptor fd;
4260 Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK);
4261 BasicType value_type = (BasicType) vCode;
4262 Reflection::field_set(&v, &fd, receiver, value_type, CHECK);
4263 JVM_END
4264
4265
4266 // Method /////////////////////////////////////////////////////////////////////////////////////////// 4023 // Method ///////////////////////////////////////////////////////////////////////////////////////////
4267 4024
4268 JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)) 4025 JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
4269 JVMWrapper("JVM_InvokeMethod"); 4026 JVMWrapper("JVM_InvokeMethod");
4270 Handle method_handle; 4027 Handle method_handle;
4299 if (JvmtiExport::should_post_vm_object_alloc()) { 4056 if (JvmtiExport::should_post_vm_object_alloc()) {
4300 JvmtiExport::post_vm_object_alloc(JavaThread::current(), result); 4057 JvmtiExport::post_vm_object_alloc(JavaThread::current(), result);
4301 } 4058 }
4302 return res; 4059 return res;
4303 JVM_END 4060 JVM_END
4304
4305 #endif /* SUPPORT_OLD_REFLECTION */
4306 4061
4307 // Atomic /////////////////////////////////////////////////////////////////////////////////////////// 4062 // Atomic ///////////////////////////////////////////////////////////////////////////////////////////
4308 4063
4309 JVM_LEAF(jboolean, JVM_SupportsCX8()) 4064 JVM_LEAF(jboolean, JVM_SupportsCX8())
4310 JVMWrapper("JVM_SupportsCX8"); 4065 JVMWrapper("JVM_SupportsCX8");