1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "java_lang_reflect_Field.h" 18 19#include "class_linker.h" 20#include "class_linker-inl.h" 21#include "common_throws.h" 22#include "dex_file-inl.h" 23#include "jni_internal.h" 24#include "mirror/class-inl.h" 25#include "mirror/field.h" 26#include "reflection-inl.h" 27#include "scoped_fast_native_object_access.h" 28#include "utils.h" 29 30namespace art { 31 32template<bool kIsSet> 33ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::Field* field, 34 mirror::Object* obj) 35 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 36 if (kIsSet && field->IsFinal()) { 37 ThrowIllegalAccessException( 38 StringPrintf("Cannot set %s field %s of class %s", 39 PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(), 40 PrettyField(field->GetArtField()).c_str(), 41 field->GetDeclaringClass() == nullptr ? "null" : 42 PrettyClass(field->GetDeclaringClass()).c_str()).c_str()); 43 return false; 44 } 45 mirror::Class* calling_class = nullptr; 46 if (!VerifyAccess(self, obj, field->GetDeclaringClass(), field->GetAccessFlags(), 47 &calling_class, 1)) { 48 ThrowIllegalAccessException( 49 StringPrintf("Class %s cannot access %s field %s of class %s", 50 calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(), 51 PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(), 52 PrettyField(field->GetArtField()).c_str(), 53 field->GetDeclaringClass() == nullptr ? "null" : 54 PrettyClass(field->GetDeclaringClass()).c_str()).c_str()); 55 return false; 56 } 57 return true; 58} 59 60template<bool kAllowReferences> 61ALWAYS_INLINE inline static bool GetFieldValue(mirror::Object* o, mirror::Field* f, 62 Primitive::Type field_type, JValue* value) 63 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 64 DCHECK_EQ(value->GetJ(), INT64_C(0)); 65 MemberOffset offset(f->GetOffset()); 66 const bool is_volatile = f->IsVolatile(); 67 switch (field_type) { 68 case Primitive::kPrimBoolean: 69 value->SetZ(is_volatile ? o->GetFieldBooleanVolatile(offset) : o->GetFieldBoolean(offset)); 70 return true; 71 case Primitive::kPrimByte: 72 value->SetB(is_volatile ? o->GetFieldByteVolatile(offset) : o->GetFieldByte(offset)); 73 return true; 74 case Primitive::kPrimChar: 75 value->SetC(is_volatile ? o->GetFieldCharVolatile(offset) : o->GetFieldChar(offset)); 76 return true; 77 case Primitive::kPrimInt: 78 case Primitive::kPrimFloat: 79 value->SetI(is_volatile ? o->GetField32Volatile(offset) : o->GetField32(offset)); 80 return true; 81 case Primitive::kPrimLong: 82 case Primitive::kPrimDouble: 83 value->SetJ(is_volatile ? o->GetField64Volatile(offset) : o->GetField64(offset)); 84 return true; 85 case Primitive::kPrimShort: 86 value->SetS(is_volatile ? o->GetFieldShortVolatile(offset) : o->GetFieldShort(offset)); 87 return true; 88 case Primitive::kPrimNot: 89 if (kAllowReferences) { 90 value->SetL(is_volatile ? o->GetFieldObjectVolatile<mirror::Object>(offset) : 91 o->GetFieldObject<mirror::Object>(offset)); 92 return true; 93 } 94 // Else break to report an error. 95 break; 96 case Primitive::kPrimVoid: 97 // Never okay. 98 break; 99 } 100 ThrowIllegalArgumentException( 101 StringPrintf("Not a primitive field: %s", PrettyField(f->GetArtField()).c_str()).c_str()); 102 return false; 103} 104 105ALWAYS_INLINE inline static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa, 106 jobject j_rcvr, mirror::Field** f, 107 mirror::Object** class_or_rcvr) 108 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 109 soa.Self()->AssertThreadSuspensionIsAllowable(); 110 mirror::Class* declaringClass = (*f)->GetDeclaringClass(); 111 if ((*f)->IsStatic()) { 112 if (UNLIKELY(!declaringClass->IsInitialized())) { 113 StackHandleScope<2> hs(soa.Self()); 114 HandleWrapper<mirror::Field> h_f(hs.NewHandleWrapper(f)); 115 HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&declaringClass)); 116 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); 117 if (UNLIKELY(!class_linker->EnsureInitialized(soa.Self(), h_klass, true, true))) { 118 DCHECK(soa.Self()->IsExceptionPending()); 119 return false; 120 } 121 } 122 *class_or_rcvr = declaringClass; 123 return true; 124 } 125 *class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr); 126 if (!VerifyObjectIsClass(*class_or_rcvr, declaringClass)) { 127 DCHECK(soa.Self()->IsExceptionPending()); 128 return false; 129 } 130 return true; 131} 132 133static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) { 134 ScopedFastNativeObjectAccess soa(env); 135 mirror::Field* f = soa.Decode<mirror::Field*>(javaField); 136 mirror::Object* o = nullptr; 137 if (!CheckReceiver(soa, javaObj, &f, &o)) { 138 DCHECK(soa.Self()->IsExceptionPending()); 139 return nullptr; 140 } 141 // If field is not set to be accessible, verify it can be accessed by the caller. 142 if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) { 143 DCHECK(soa.Self()->IsExceptionPending()); 144 return nullptr; 145 } 146 // We now don't expect suspension unless an exception is thrown. 147 // Get the field's value, boxing if necessary. 148 Primitive::Type field_type = f->GetTypeAsPrimitiveType(); 149 JValue value; 150 if (!GetFieldValue<true>(o, f, field_type, &value)) { 151 DCHECK(soa.Self()->IsExceptionPending()); 152 return nullptr; 153 } 154 return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value)); 155} 156 157template<Primitive::Type kPrimitiveType> 158ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, 159 jobject javaObj) { 160 ScopedFastNativeObjectAccess soa(env); 161 mirror::Field* f = soa.Decode<mirror::Field*>(javaField); 162 mirror::Object* o = nullptr; 163 if (!CheckReceiver(soa, javaObj, &f, &o)) { 164 DCHECK(soa.Self()->IsExceptionPending()); 165 return JValue(); 166 } 167 168 // If field is not set to be accessible, verify it can be accessed by the caller. 169 if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) { 170 DCHECK(soa.Self()->IsExceptionPending()); 171 return JValue(); 172 } 173 174 // We now don't expect suspension unless an exception is thrown. 175 // Read the value. 176 Primitive::Type field_type = f->GetTypeAsPrimitiveType(); 177 JValue field_value; 178 if (field_type == kPrimitiveType) { 179 // This if statement should get optimized out since we only pass in valid primitive types. 180 if (UNLIKELY(!GetFieldValue<false>(o, f, kPrimitiveType, &field_value))) { 181 DCHECK(soa.Self()->IsExceptionPending()); 182 return JValue(); 183 } 184 return field_value; 185 } 186 if (!GetFieldValue<false>(o, f, field_type, &field_value)) { 187 DCHECK(soa.Self()->IsExceptionPending()); 188 return JValue(); 189 } 190 // Widen it if necessary (and possible). 191 JValue wide_value; 192 if (!ConvertPrimitiveValue(false, field_type, kPrimitiveType, field_value, 193 &wide_value)) { 194 DCHECK(soa.Self()->IsExceptionPending()); 195 return JValue(); 196 } 197 return wide_value; 198} 199 200static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj) { 201 return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj).GetZ(); 202} 203 204static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj) { 205 return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj).GetB(); 206} 207 208static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj) { 209 return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj).GetC(); 210} 211 212static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj) { 213 return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj).GetD(); 214} 215 216static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj) { 217 return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj).GetF(); 218} 219 220static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj) { 221 return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj).GetI(); 222} 223 224static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj) { 225 return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj).GetJ(); 226} 227 228static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) { 229 return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj).GetS(); 230} 231 232ALWAYS_INLINE inline static void SetFieldValue(mirror::Object* o, mirror::Field* f, 233 Primitive::Type field_type, bool allow_references, 234 const JValue& new_value) 235 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 236 DCHECK(f->GetDeclaringClass()->IsInitialized()); 237 MemberOffset offset(f->GetOffset()); 238 const bool is_volatile = f->IsVolatile(); 239 switch (field_type) { 240 case Primitive::kPrimBoolean: 241 if (is_volatile) { 242 o->SetFieldBooleanVolatile<false>(offset, new_value.GetZ()); 243 } else { 244 o->SetFieldBoolean<false>(offset, new_value.GetZ()); 245 } 246 break; 247 case Primitive::kPrimByte: 248 if (is_volatile) { 249 o->SetFieldBooleanVolatile<false>(offset, new_value.GetB()); 250 } else { 251 o->SetFieldBoolean<false>(offset, new_value.GetB()); 252 } 253 break; 254 case Primitive::kPrimChar: 255 if (is_volatile) { 256 o->SetFieldCharVolatile<false>(offset, new_value.GetC()); 257 } else { 258 o->SetFieldChar<false>(offset, new_value.GetC()); 259 } 260 break; 261 case Primitive::kPrimInt: 262 case Primitive::kPrimFloat: 263 if (is_volatile) { 264 o->SetField32Volatile<false>(offset, new_value.GetI()); 265 } else { 266 o->SetField32<false>(offset, new_value.GetI()); 267 } 268 break; 269 case Primitive::kPrimLong: 270 case Primitive::kPrimDouble: 271 if (is_volatile) { 272 o->SetField64Volatile<false>(offset, new_value.GetJ()); 273 } else { 274 o->SetField64<false>(offset, new_value.GetJ()); 275 } 276 break; 277 case Primitive::kPrimShort: 278 if (is_volatile) { 279 o->SetFieldShortVolatile<false>(offset, new_value.GetS()); 280 } else { 281 o->SetFieldShort<false>(offset, new_value.GetS()); 282 } 283 break; 284 case Primitive::kPrimNot: 285 if (allow_references) { 286 if (is_volatile) { 287 o->SetFieldObjectVolatile<false>(offset, new_value.GetL()); 288 } else { 289 o->SetFieldObject<false>(offset, new_value.GetL()); 290 } 291 break; 292 } 293 // Else fall through to report an error. 294 FALLTHROUGH_INTENDED; 295 case Primitive::kPrimVoid: 296 // Never okay. 297 ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s", 298 PrettyField(f->GetArtField()).c_str()).c_str()); 299 return; 300 } 301} 302 303static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) { 304 ScopedFastNativeObjectAccess soa(env); 305 mirror::Field* f = soa.Decode<mirror::Field*>(javaField); 306 // Check that the receiver is non-null and an instance of the field's declaring class. 307 mirror::Object* o = nullptr; 308 if (!CheckReceiver(soa, javaObj, &f, &o)) { 309 DCHECK(soa.Self()->IsExceptionPending()); 310 return; 311 } 312 mirror::Class* field_type; 313 const char* field_type_desciptor = f->GetArtField()->GetTypeDescriptor(); 314 Primitive::Type field_prim_type = Primitive::GetType(field_type_desciptor[0]); 315 if (field_prim_type == Primitive::kPrimNot) { 316 field_type = f->GetType(); 317 DCHECK(field_type != nullptr); 318 } else { 319 field_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(field_type_desciptor[0]); 320 } 321 // We now don't expect suspension unless an exception is thrown. 322 // Unbox the value, if necessary. 323 mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue); 324 JValue unboxed_value; 325 if (!UnboxPrimitiveForField(boxed_value, field_type, f->GetArtField(), &unboxed_value)) { 326 DCHECK(soa.Self()->IsExceptionPending()); 327 return; 328 } 329 // If field is not set to be accessible, verify it can be accessed by the caller. 330 if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) { 331 DCHECK(soa.Self()->IsExceptionPending()); 332 return; 333 } 334 SetFieldValue(o, f, field_prim_type, true, unboxed_value); 335} 336 337template<Primitive::Type kPrimitiveType> 338static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, 339 const JValue& new_value) { 340 ScopedFastNativeObjectAccess soa(env); 341 mirror::Field* f = soa.Decode<mirror::Field*>(javaField); 342 mirror::Object* o = nullptr; 343 if (!CheckReceiver(soa, javaObj, &f, &o)) { 344 return; 345 } 346 Primitive::Type field_type = f->GetTypeAsPrimitiveType(); 347 if (UNLIKELY(field_type == Primitive::kPrimNot)) { 348 ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s", 349 PrettyField(f->GetArtField()).c_str()).c_str()); 350 return; 351 } 352 353 // Widen the value if necessary (and possible). 354 JValue wide_value; 355 if (!ConvertPrimitiveValue(false, kPrimitiveType, field_type, new_value, &wide_value)) { 356 DCHECK(soa.Self()->IsExceptionPending()); 357 return; 358 } 359 360 // If field is not set to be accessible, verify it can be accessed by the caller. 361 if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) { 362 DCHECK(soa.Self()->IsExceptionPending()); 363 return; 364 } 365 366 // Write the value. 367 SetFieldValue(o, f, field_type, false, wide_value); 368} 369 370static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) { 371 JValue value; 372 value.SetZ(z); 373 SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value); 374} 375 376static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b) { 377 JValue value; 378 value.SetB(b); 379 SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value); 380} 381 382static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c) { 383 JValue value; 384 value.SetC(c); 385 SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value); 386} 387 388static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d) { 389 JValue value; 390 value.SetD(d); 391 SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value); 392} 393 394static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f) { 395 JValue value; 396 value.SetF(f); 397 SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value); 398} 399 400static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i) { 401 JValue value; 402 value.SetI(i); 403 SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value); 404} 405 406static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j) { 407 JValue value; 408 value.SetJ(j); 409 SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value); 410} 411 412static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s) { 413 JValue value; 414 value.SetS(s); 415 SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value); 416} 417 418static JNINativeMethod gMethods[] = { 419 NATIVE_METHOD(Field, get, "!(Ljava/lang/Object;)Ljava/lang/Object;"), 420 NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;)Z"), 421 NATIVE_METHOD(Field, getByte, "!(Ljava/lang/Object;)B"), 422 NATIVE_METHOD(Field, getChar, "!(Ljava/lang/Object;)C"), 423 NATIVE_METHOD(Field, getDouble, "!(Ljava/lang/Object;)D"), 424 NATIVE_METHOD(Field, getFloat, "!(Ljava/lang/Object;)F"), 425 NATIVE_METHOD(Field, getInt, "!(Ljava/lang/Object;)I"), 426 NATIVE_METHOD(Field, getLong, "!(Ljava/lang/Object;)J"), 427 NATIVE_METHOD(Field, getShort, "!(Ljava/lang/Object;)S"), 428 NATIVE_METHOD(Field, set, "!(Ljava/lang/Object;Ljava/lang/Object;)V"), 429 NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;Z)V"), 430 NATIVE_METHOD(Field, setByte, "!(Ljava/lang/Object;B)V"), 431 NATIVE_METHOD(Field, setChar, "!(Ljava/lang/Object;C)V"), 432 NATIVE_METHOD(Field, setDouble, "!(Ljava/lang/Object;D)V"), 433 NATIVE_METHOD(Field, setFloat, "!(Ljava/lang/Object;F)V"), 434 NATIVE_METHOD(Field, setInt, "!(Ljava/lang/Object;I)V"), 435 NATIVE_METHOD(Field, setLong, "!(Ljava/lang/Object;J)V"), 436 NATIVE_METHOD(Field, setShort, "!(Ljava/lang/Object;S)V"), 437}; 438 439void register_java_lang_reflect_Field(JNIEnv* env) { 440 REGISTER_NATIVE_METHODS("java/lang/reflect/Field"); 441} 442 443} // namespace art 444