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 "jni_internal.h"
     22 #include "mirror/art_field-inl.h"
     23 #include "mirror/class-inl.h"
     24 #include "object_utils.h"
     25 #include "reflection.h"
     26 #include "scoped_thread_state_change.h"
     27 
     28 namespace art {
     29 
     30 static bool GetFieldValue(const ScopedObjectAccess& soa, mirror::Object* o, mirror::ArtField* f,
     31                           JValue& value, bool allow_references)
     32     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     33   DCHECK_EQ(value.GetJ(), 0LL);
     34   if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(f->GetDeclaringClass(),
     35                                                                true, true)) {
     36     return false;
     37   }
     38   switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
     39   case Primitive::kPrimBoolean:
     40     value.SetZ(f->GetBoolean(o));
     41     return true;
     42   case Primitive::kPrimByte:
     43     value.SetB(f->GetByte(o));
     44     return true;
     45   case Primitive::kPrimChar:
     46     value.SetC(f->GetChar(o));
     47     return true;
     48   case Primitive::kPrimDouble:
     49     value.SetD(f->GetDouble(o));
     50     return true;
     51   case Primitive::kPrimFloat:
     52     value.SetF(f->GetFloat(o));
     53     return true;
     54   case Primitive::kPrimInt:
     55     value.SetI(f->GetInt(o));
     56     return true;
     57   case Primitive::kPrimLong:
     58     value.SetJ(f->GetLong(o));
     59     return true;
     60   case Primitive::kPrimShort:
     61     value.SetS(f->GetShort(o));
     62     return true;
     63   case Primitive::kPrimNot:
     64     if (allow_references) {
     65       value.SetL(f->GetObject(o));
     66       return true;
     67     }
     68     // Else break to report an error.
     69     break;
     70   case Primitive::kPrimVoid:
     71     // Never okay.
     72     break;
     73   }
     74   ThrowIllegalArgumentException(NULL,
     75                                 StringPrintf("Not a primitive field: %s",
     76                                              PrettyField(f).c_str()).c_str());
     77   return false;
     78 }
     79 
     80 static bool CheckReceiver(const ScopedObjectAccess& soa, jobject j_rcvr, mirror::ArtField* f,
     81                           mirror::Object*& class_or_rcvr)
     82     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     83   if (f->IsStatic()) {
     84     class_or_rcvr = f->GetDeclaringClass();
     85     return true;
     86   }
     87 
     88   class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr);
     89   mirror::Class* declaringClass = f->GetDeclaringClass();
     90   if (!VerifyObjectInClass(class_or_rcvr, declaringClass)) {
     91     return false;
     92   }
     93   return true;
     94 }
     95 
     96 static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
     97   ScopedObjectAccess soa(env);
     98   mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField));
     99   mirror::Object* o = NULL;
    100   if (!CheckReceiver(soa, javaObj, f, o)) {
    101     return NULL;
    102   }
    103 
    104   // Get the field's value, boxing if necessary.
    105   JValue value;
    106   if (!GetFieldValue(soa, o, f, value, true)) {
    107     return NULL;
    108   }
    109   return
    110       soa.AddLocalReference<jobject>(BoxPrimitive(FieldHelper(f).GetTypeAsPrimitiveType(), value));
    111 }
    112 
    113 static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
    114                                 char dst_descriptor) {
    115   ScopedObjectAccess soa(env);
    116   mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField));
    117   mirror::Object* o = NULL;
    118   if (!CheckReceiver(soa, javaObj, f, o)) {
    119     return JValue();
    120   }
    121 
    122   // Read the value.
    123   JValue field_value;
    124   if (!GetFieldValue(soa, o, f, field_value, false)) {
    125     return JValue();
    126   }
    127 
    128   // Widen it if necessary (and possible).
    129   JValue wide_value;
    130   mirror::Class* dst_type =
    131       Runtime::Current()->GetClassLinker()->FindPrimitiveClass(dst_descriptor);
    132   if (!ConvertPrimitiveValue(NULL, false, FieldHelper(f).GetTypeAsPrimitiveType(),
    133                              dst_type->GetPrimitiveType(), field_value, wide_value)) {
    134     return JValue();
    135   }
    136   return wide_value;
    137 }
    138 
    139 static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj) {
    140   return GetPrimitiveField(env, javaField, javaObj, 'Z').GetZ();
    141 }
    142 
    143 static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj) {
    144   return GetPrimitiveField(env, javaField, javaObj, 'B').GetB();
    145 }
    146 
    147 static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj) {
    148   return GetPrimitiveField(env, javaField, javaObj, 'C').GetC();
    149 }
    150 
    151 static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj) {
    152   return GetPrimitiveField(env, javaField, javaObj, 'D').GetD();
    153 }
    154 
    155 static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj) {
    156   return GetPrimitiveField(env, javaField, javaObj, 'F').GetF();
    157 }
    158 
    159 static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj) {
    160   return GetPrimitiveField(env, javaField, javaObj, 'I').GetI();
    161 }
    162 
    163 static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj) {
    164   return GetPrimitiveField(env, javaField, javaObj, 'J').GetJ();
    165 }
    166 
    167 static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) {
    168   return GetPrimitiveField(env, javaField, javaObj, 'S').GetS();
    169 }
    170 
    171 static void SetFieldValue(mirror::Object* o, mirror::ArtField* f, const JValue& new_value,
    172                           bool allow_references)
    173     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    174   if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(f->GetDeclaringClass(),
    175                                                                true, true)) {
    176     return;
    177   }
    178   switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
    179   case Primitive::kPrimBoolean:
    180     f->SetBoolean(o, new_value.GetZ());
    181     break;
    182   case Primitive::kPrimByte:
    183     f->SetByte(o, new_value.GetB());
    184     break;
    185   case Primitive::kPrimChar:
    186     f->SetChar(o, new_value.GetC());
    187     break;
    188   case Primitive::kPrimDouble:
    189     f->SetDouble(o, new_value.GetD());
    190     break;
    191   case Primitive::kPrimFloat:
    192     f->SetFloat(o, new_value.GetF());
    193     break;
    194   case Primitive::kPrimInt:
    195     f->SetInt(o, new_value.GetI());
    196     break;
    197   case Primitive::kPrimLong:
    198     f->SetLong(o, new_value.GetJ());
    199     break;
    200   case Primitive::kPrimShort:
    201     f->SetShort(o, new_value.GetS());
    202     break;
    203   case Primitive::kPrimNot:
    204     if (allow_references) {
    205       f->SetObject(o, new_value.GetL());
    206       break;
    207     }
    208     // Else fall through to report an error.
    209   case Primitive::kPrimVoid:
    210     // Never okay.
    211     ThrowIllegalArgumentException(NULL, StringPrintf("Not a primitive field: %s",
    212                                                      PrettyField(f).c_str()).c_str());
    213     return;
    214   }
    215 
    216   // Special handling for final fields on SMP systems.
    217   // We need a store/store barrier here (JMM requirement).
    218   if (f->IsFinal()) {
    219     ANDROID_MEMBAR_STORE();
    220   }
    221 }
    222 
    223 static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
    224   ScopedObjectAccess soa(env);
    225   mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField));
    226 
    227   // Unbox the value, if necessary.
    228   mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
    229   JValue unboxed_value;
    230   if (!UnboxPrimitiveForField(boxed_value, FieldHelper(f).GetType(), unboxed_value, f)) {
    231     return;
    232   }
    233 
    234   // Check that the receiver is non-null and an instance of the field's declaring class.
    235   mirror::Object* o = NULL;
    236   if (!CheckReceiver(soa, javaObj, f, o)) {
    237     return;
    238   }
    239 
    240   SetFieldValue(o, f, unboxed_value, true);
    241 }
    242 
    243 static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor,
    244                               const JValue& new_value) {
    245   ScopedObjectAccess soa(env);
    246   mirror::ArtField* f = soa.DecodeField(env->FromReflectedField(javaField));
    247   mirror::Object* o = NULL;
    248   if (!CheckReceiver(soa, javaObj, f, o)) {
    249     return;
    250   }
    251   FieldHelper fh(f);
    252   if (!fh.IsPrimitiveType()) {
    253     ThrowIllegalArgumentException(NULL, StringPrintf("Not a primitive field: %s",
    254                                                      PrettyField(f).c_str()).c_str());
    255     return;
    256   }
    257 
    258   // Widen the value if necessary (and possible).
    259   JValue wide_value;
    260   mirror::Class* src_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(src_descriptor);
    261   if (!ConvertPrimitiveValue(NULL, false, src_type->GetPrimitiveType(), fh.GetTypeAsPrimitiveType(),
    262                              new_value, wide_value)) {
    263     return;
    264   }
    265 
    266   // Write the value.
    267   SetFieldValue(o, f, wide_value, false);
    268 }
    269 
    270 static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) {
    271   JValue value;
    272   value.SetZ(z);
    273   SetPrimitiveField(env, javaField, javaObj, 'Z', value);
    274 }
    275 
    276 static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b) {
    277   JValue value;
    278   value.SetB(b);
    279   SetPrimitiveField(env, javaField, javaObj, 'B', value);
    280 }
    281 
    282 static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c) {
    283   JValue value;
    284   value.SetC(c);
    285   SetPrimitiveField(env, javaField, javaObj, 'C', value);
    286 }
    287 
    288 static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d) {
    289   JValue value;
    290   value.SetD(d);
    291   SetPrimitiveField(env, javaField, javaObj, 'D', value);
    292 }
    293 
    294 static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f) {
    295   JValue value;
    296   value.SetF(f);
    297   SetPrimitiveField(env, javaField, javaObj, 'F', value);
    298 }
    299 
    300 static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i) {
    301   JValue value;
    302   value.SetI(i);
    303   SetPrimitiveField(env, javaField, javaObj, 'I', value);
    304 }
    305 
    306 static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j) {
    307   JValue value;
    308   value.SetJ(j);
    309   SetPrimitiveField(env, javaField, javaObj, 'J', value);
    310 }
    311 
    312 static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s) {
    313   JValue value;
    314   value.SetS(s);
    315   SetPrimitiveField(env, javaField, javaObj, 'S', value);
    316 }
    317 
    318 static JNINativeMethod gMethods[] = {
    319   NATIVE_METHOD(Field, get,        "(Ljava/lang/Object;)Ljava/lang/Object;"),
    320   NATIVE_METHOD(Field, getBoolean, "(Ljava/lang/Object;)Z"),
    321   NATIVE_METHOD(Field, getByte,    "(Ljava/lang/Object;)B"),
    322   NATIVE_METHOD(Field, getChar,    "(Ljava/lang/Object;)C"),
    323   NATIVE_METHOD(Field, getDouble,  "(Ljava/lang/Object;)D"),
    324   NATIVE_METHOD(Field, getFloat,   "(Ljava/lang/Object;)F"),
    325   NATIVE_METHOD(Field, getInt,     "(Ljava/lang/Object;)I"),
    326   NATIVE_METHOD(Field, getLong,    "(Ljava/lang/Object;)J"),
    327   NATIVE_METHOD(Field, getShort,   "(Ljava/lang/Object;)S"),
    328   NATIVE_METHOD(Field, set,        "(Ljava/lang/Object;Ljava/lang/Object;)V"),
    329   NATIVE_METHOD(Field, setBoolean, "(Ljava/lang/Object;Z)V"),
    330   NATIVE_METHOD(Field, setByte,    "(Ljava/lang/Object;B)V"),
    331   NATIVE_METHOD(Field, setChar,    "(Ljava/lang/Object;C)V"),
    332   NATIVE_METHOD(Field, setDouble,  "(Ljava/lang/Object;D)V"),
    333   NATIVE_METHOD(Field, setFloat,   "(Ljava/lang/Object;F)V"),
    334   NATIVE_METHOD(Field, setInt,     "(Ljava/lang/Object;I)V"),
    335   NATIVE_METHOD(Field, setLong,    "(Ljava/lang/Object;J)V"),
    336   NATIVE_METHOD(Field, setShort,   "(Ljava/lang/Object;S)V"),
    337 };
    338 
    339 void register_java_lang_reflect_Field(JNIEnv* env) {
    340   REGISTER_NATIVE_METHODS("java/lang/reflect/Field");
    341 }
    342 
    343 }  // namespace art
    344