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