Mercurial > hg > graal-compiler
comparison src/share/vm/prims/jvm.cpp @ 3895: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
3894:b27c72d69fd1 | 3895:19241ae0d839 |
---|---|
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"); |