Home | History | Annotate | Download | only in native
      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 "class_linker.h"
     18 #include "class_linker-inl.h"
     19 #include "common_throws.h"
     20 #include "dex_file-inl.h"
     21 #include "field_helper.h"
     22 #include "jni_internal.h"
     23 #include "mirror/art_field-inl.h"
     24 #include "mirror/art_method-inl.h"
     25 #include "mirror/class-inl.h"
     26 #include "reflection-inl.h"
     27 #include "scoped_fast_native_object_access.h"
     28 
     29 namespace art {
     30 
     31 template<bool kIsSet>
     32 ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::ArtField* field,
     33                                                    mirror::Object* obj)
     34     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     35   if (kIsSet && field->IsFinal()) {
     36     ThrowIllegalAccessException(nullptr, StringPrintf("Cannot set final field: %s",
     37                                                       PrettyField(field).c_str()).c_str());
     38     return false;
     39   }
     40   if (!VerifyAccess(self, obj, field->GetDeclaringClass(), field->GetAccessFlags())) {
     41     ThrowIllegalAccessException(nullptr, StringPrintf("Cannot access field: %s",
     42                                                       PrettyField(field).c_str()).c_str());
     43     return false;
     44   }
     45   return true;
     46 }
     47 
     48 template<bool kAllowReferences>
     49 ALWAYS_INLINE inline static bool GetFieldValue(
     50     const ScopedFastNativeObjectAccess& soa, mirror::Object* o, mirror::ArtField* f,
     51     Primitive::Type field_type, JValue* value)
     52     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     53   DCHECK_EQ(value->GetJ(), INT64_C(0));
     54   switch (field_type) {
     55     case Primitive::kPrimBoolean:
     56       value->SetZ(f->GetBoolean(o));
     57       return true;
     58     case Primitive::kPrimByte:
     59       value->SetB(f->GetByte(o));
     60       return true;
     61     case Primitive::kPrimChar:
     62       value->SetC(f->GetChar(o));
     63       return true;
     64     case Primitive::kPrimDouble:
     65       value->SetD(f->GetDouble(o));
     66       return true;
     67     case Primitive::kPrimFloat:
     68       value->SetF(f->GetFloat(o));
     69       return true;
     70     case Primitive::kPrimInt:
     71       value->SetI(f->GetInt(o));
     72       return true;
     73     case Primitive::kPrimLong:
     74       value->SetJ(f->GetLong(o));
     75       return true;
     76     case Primitive::kPrimShort:
     77       value->SetS(f->GetShort(o));
     78       return true;
     79     case Primitive::kPrimNot:
     80       if (kAllowReferences) {
     81         value->SetL(f->GetObject(o));
     82         return true;
     83       }
     84       // Else break to report an error.
     85       break;
     86     case Primitive::kPrimVoid:
     87       // Never okay.
     88       break;
     89   }
     90   ThrowIllegalArgumentException(nullptr, StringPrintf("Not a primitive field: %s",
     91                                                       PrettyField(f).c_str()).c_str());
     92   return false;
     93 }
     94 
     95 ALWAYS_INLINE inline static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa,
     96                                                jobject j_rcvr, mirror::ArtField** f,
     97                                                mirror::Object** class_or_rcvr)
     98     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     99   soa.Self()->AssertThreadSuspensionIsAllowable();
    100   mirror::Class* declaringClass = (*f)->GetDeclaringClass();
    101   if ((*f)->IsStatic()) {
    102     if (UNLIKELY(!declaringClass->IsInitialized())) {
    103       ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    104       StackHandleScope<2> hs(soa.Self());
    105       HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(f));
    106       HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&declaringClass));
    107       if (UNLIKELY(!class_linker->EnsureInitialized(h_klass, true, true))) {
    108         DCHECK(soa.Self()->IsExceptionPending());
    109         return false;
    110       }
    111     }
    112     *class_or_rcvr = declaringClass;
    113     return true;
    114   }
    115   *class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr);
    116   if (!VerifyObjectIsClass(*class_or_rcvr, declaringClass)) {
    117     DCHECK(soa.Self()->IsExceptionPending());
    118     return false;
    119   }
    120   return true;
    121 }
    122 
    123 static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
    124   ScopedFastNativeObjectAccess soa(env);
    125   mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
    126   mirror::Object* o = nullptr;
    127   if (!CheckReceiver(soa, javaObj, &f, &o)) {
    128     DCHECK(soa.Self()->IsExceptionPending());
    129     return nullptr;
    130   }
    131   // If field is not set to be accessible, verify it can be accessed by the caller.
    132   if ((accessible == JNI_FALSE) && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
    133     DCHECK(soa.Self()->IsExceptionPending());
    134     return nullptr;
    135   }
    136   // We now don't expect suspension unless an exception is thrown.
    137   // Get the field's value, boxing if necessary.
    138   Primitive::Type field_type = f->GetTypeAsPrimitiveType();
    139   JValue value;
    140   if (!GetFieldValue<true>(soa, o, f, field_type, &value)) {
    141     DCHECK(soa.Self()->IsExceptionPending());
    142     return nullptr;
    143   }
    144   return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value));
    145 }
    146 
    147 template<Primitive::Type kPrimitiveType>
    148 ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaField,
    149                                                      jobject javaObj, jboolean accessible) {
    150   ScopedFastNativeObjectAccess soa(env);
    151   mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
    152   mirror::Object* o = nullptr;
    153   if (!CheckReceiver(soa, javaObj, &f, &o)) {
    154     DCHECK(soa.Self()->IsExceptionPending());
    155     return JValue();
    156   }
    157 
    158   // If field is not set to be accessible, verify it can be accessed by the caller.
    159   if (accessible == JNI_FALSE && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
    160     DCHECK(soa.Self()->IsExceptionPending());
    161     return JValue();
    162   }
    163 
    164   // We now don't expect suspension unless an exception is thrown.
    165   // Read the value.
    166   Primitive::Type field_type = f->GetTypeAsPrimitiveType();
    167   JValue field_value;
    168   if (field_type == kPrimitiveType) {
    169     // This if statement should get optimized out since we only pass in valid primitive types.
    170     if (UNLIKELY(!GetFieldValue<false>(soa, o, f, kPrimitiveType, &field_value))) {
    171       DCHECK(soa.Self()->IsExceptionPending());
    172       return JValue();
    173     }
    174     return field_value;
    175   }
    176   if (!GetFieldValue<false>(soa, o, f, field_type, &field_value)) {
    177     DCHECK(soa.Self()->IsExceptionPending());
    178     return JValue();
    179   }
    180   // Widen it if necessary (and possible).
    181   JValue wide_value;
    182   if (!ConvertPrimitiveValue(nullptr, false, field_type, kPrimitiveType, field_value,
    183                              &wide_value)) {
    184     DCHECK(soa.Self()->IsExceptionPending());
    185     return JValue();
    186   }
    187   return wide_value;
    188 }
    189 
    190 static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj,
    191                                  jboolean accessible) {
    192   return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, accessible).GetZ();
    193 }
    194 
    195 static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
    196   return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, accessible).GetB();
    197 }
    198 
    199 static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
    200   return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, accessible).GetC();
    201 }
    202 
    203 static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj,
    204                                jboolean accessible) {
    205   return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, accessible).GetD();
    206 }
    207 
    208 static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
    209   return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, accessible).GetF();
    210 }
    211 
    212 static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
    213   return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, accessible).GetI();
    214 }
    215 
    216 static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
    217   return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, accessible).GetJ();
    218 }
    219 
    220 static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
    221   return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, accessible).GetS();
    222 }
    223 
    224 static void SetFieldValue(ScopedFastNativeObjectAccess& soa, mirror::Object* o,
    225                           mirror::ArtField* f, Primitive::Type field_type, bool allow_references,
    226                           const JValue& new_value)
    227     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    228   DCHECK(f->GetDeclaringClass()->IsInitialized());
    229   switch (field_type) {
    230   case Primitive::kPrimBoolean:
    231     f->SetBoolean<false>(o, new_value.GetZ());
    232     break;
    233   case Primitive::kPrimByte:
    234     f->SetByte<false>(o, new_value.GetB());
    235     break;
    236   case Primitive::kPrimChar:
    237     f->SetChar<false>(o, new_value.GetC());
    238     break;
    239   case Primitive::kPrimDouble:
    240     f->SetDouble<false>(o, new_value.GetD());
    241     break;
    242   case Primitive::kPrimFloat:
    243     f->SetFloat<false>(o, new_value.GetF());
    244     break;
    245   case Primitive::kPrimInt:
    246     f->SetInt<false>(o, new_value.GetI());
    247     break;
    248   case Primitive::kPrimLong:
    249     f->SetLong<false>(o, new_value.GetJ());
    250     break;
    251   case Primitive::kPrimShort:
    252     f->SetShort<false>(o, new_value.GetS());
    253     break;
    254   case Primitive::kPrimNot:
    255     if (allow_references) {
    256       f->SetObject<false>(o, new_value.GetL());
    257       break;
    258     }
    259     // Else fall through to report an error.
    260   case Primitive::kPrimVoid:
    261     // Never okay.
    262     ThrowIllegalArgumentException(nullptr, StringPrintf("Not a primitive field: %s",
    263                                                         PrettyField(f).c_str()).c_str());
    264     return;
    265   }
    266 }
    267 
    268 static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue,
    269                       jboolean accessible) {
    270   ScopedFastNativeObjectAccess soa(env);
    271   mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
    272   // Check that the receiver is non-null and an instance of the field's declaring class.
    273   mirror::Object* o = nullptr;
    274   if (!CheckReceiver(soa, javaObj, &f, &o)) {
    275     DCHECK(soa.Self()->IsExceptionPending());
    276     return;
    277   }
    278   mirror::Class* field_type;
    279   const char* field_type_desciptor = f->GetTypeDescriptor();
    280   Primitive::Type field_prim_type = Primitive::GetType(field_type_desciptor[0]);
    281   if (field_prim_type == Primitive::kPrimNot) {
    282     StackHandleScope<2> hs(soa.Self());
    283     HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o));
    284     HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
    285     FieldHelper fh(h_f);
    286     // May cause resolution.
    287     field_type = fh.GetType(true);
    288     if (field_type == nullptr) {
    289       DCHECK(soa.Self()->IsExceptionPending());
    290       return;
    291     }
    292   } else {
    293     field_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(field_type_desciptor[0]);
    294   }
    295   // We now don't expect suspension unless an exception is thrown.
    296   // Unbox the value, if necessary.
    297   mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
    298   JValue unboxed_value;
    299   if (!UnboxPrimitiveForField(boxed_value, field_type, f, &unboxed_value)) {
    300     DCHECK(soa.Self()->IsExceptionPending());
    301     return;
    302   }
    303   // If field is not set to be accessible, verify it can be accessed by the caller.
    304   if ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
    305     DCHECK(soa.Self()->IsExceptionPending());
    306     return;
    307   }
    308   SetFieldValue(soa, o, f, field_prim_type, true, unboxed_value);
    309 }
    310 
    311 template<Primitive::Type kPrimitiveType>
    312 static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
    313                               const JValue& new_value, jboolean accessible) {
    314   ScopedFastNativeObjectAccess soa(env);
    315   mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
    316   mirror::Object* o = nullptr;
    317   if (!CheckReceiver(soa, javaObj, &f, &o)) {
    318     return;
    319   }
    320   Primitive::Type field_type = f->GetTypeAsPrimitiveType();
    321   if (UNLIKELY(field_type == Primitive::kPrimNot)) {
    322     ThrowIllegalArgumentException(nullptr, StringPrintf("Not a primitive field: %s",
    323                                                         PrettyField(f).c_str()).c_str());
    324     return;
    325   }
    326 
    327   // Widen the value if necessary (and possible).
    328   JValue wide_value;
    329   if (!ConvertPrimitiveValue(nullptr, false, kPrimitiveType, field_type, new_value, &wide_value)) {
    330     DCHECK(soa.Self()->IsExceptionPending());
    331     return;
    332   }
    333 
    334   // If field is not set to be accessible, verify it can be accessed by the caller.
    335   if ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
    336     DCHECK(soa.Self()->IsExceptionPending());
    337     return;
    338   }
    339 
    340   // Write the value.
    341   SetFieldValue(soa, o, f, field_type, false, wide_value);
    342 }
    343 
    344 static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z,
    345                              jboolean accessible) {
    346   JValue value;
    347   value.SetZ(z);
    348   SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value, accessible);
    349 }
    350 
    351 static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b,
    352                           jboolean accessible) {
    353   JValue value;
    354   value.SetB(b);
    355   SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value, accessible);
    356 }
    357 
    358 static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c,
    359                           jboolean accessible) {
    360   JValue value;
    361   value.SetC(c);
    362   SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value, accessible);
    363 }
    364 
    365 static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d,
    366                             jboolean accessible) {
    367   JValue value;
    368   value.SetD(d);
    369   SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value, accessible);
    370 }
    371 
    372 static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f,
    373                            jboolean accessible) {
    374   JValue value;
    375   value.SetF(f);
    376   SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value, accessible);
    377 }
    378 
    379 static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i,
    380                          jboolean accessible) {
    381   JValue value;
    382   value.SetI(i);
    383   SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value, accessible);
    384 }
    385 
    386 static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j,
    387                           jboolean accessible) {
    388   JValue value;
    389   value.SetJ(j);
    390   SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value, accessible);
    391 }
    392 
    393 static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s,
    394                            jboolean accessible) {
    395   JValue value;
    396   value.SetS(s);
    397   SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value, accessible);
    398 }
    399 
    400 static JNINativeMethod gMethods[] = {
    401   NATIVE_METHOD(Field, get,        "!(Ljava/lang/Object;Z)Ljava/lang/Object;"),
    402   NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;Z)Z"),
    403   NATIVE_METHOD(Field, getByte,    "!(Ljava/lang/Object;Z)B"),
    404   NATIVE_METHOD(Field, getChar,    "!(Ljava/lang/Object;Z)C"),
    405   NATIVE_METHOD(Field, getDouble,  "!(Ljava/lang/Object;Z)D"),
    406   NATIVE_METHOD(Field, getFloat,   "!(Ljava/lang/Object;Z)F"),
    407   NATIVE_METHOD(Field, getInt,     "!(Ljava/lang/Object;Z)I"),
    408   NATIVE_METHOD(Field, getLong,    "!(Ljava/lang/Object;Z)J"),
    409   NATIVE_METHOD(Field, getShort,   "!(Ljava/lang/Object;Z)S"),
    410   NATIVE_METHOD(Field, set,        "!(Ljava/lang/Object;Ljava/lang/Object;Z)V"),
    411   NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;ZZ)V"),
    412   NATIVE_METHOD(Field, setByte,    "!(Ljava/lang/Object;BZ)V"),
    413   NATIVE_METHOD(Field, setChar,    "!(Ljava/lang/Object;CZ)V"),
    414   NATIVE_METHOD(Field, setDouble,  "!(Ljava/lang/Object;DZ)V"),
    415   NATIVE_METHOD(Field, setFloat,   "!(Ljava/lang/Object;FZ)V"),
    416   NATIVE_METHOD(Field, setInt,     "!(Ljava/lang/Object;IZ)V"),
    417   NATIVE_METHOD(Field, setLong,    "!(Ljava/lang/Object;JZ)V"),
    418   NATIVE_METHOD(Field, setShort,   "!(Ljava/lang/Object;SZ)V"),
    419 };
    420 
    421 void register_java_lang_reflect_Field(JNIEnv* env) {
    422   REGISTER_NATIVE_METHODS("java/lang/reflect/Field");
    423 }
    424 
    425 }  // namespace art
    426