diff options
author | Jeff Hao <jeffhao@google.com> | 2014-03-28 21:41:16 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-03-28 21:41:17 +0000 |
commit | e759c9f01b558093466fc78f01900042120cd832 (patch) | |
tree | 73bd144098c0d096b7a0d375c85379fa3f354056 /runtime | |
parent | 26162488da23d1cbd04e6112ea458847818f1dae (diff) | |
parent | 11d5d8fffe41cc7daadbfa2ca98ecb978f3029af (diff) | |
download | art-e759c9f01b558093466fc78f01900042120cd832.zip art-e759c9f01b558093466fc78f01900042120cd832.tar.gz art-e759c9f01b558093466fc78f01900042120cd832.tar.bz2 |
Merge "Add access checks to Method and Field reflection."
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/common_throws.cc | 6 | ||||
-rw-r--r-- | runtime/common_throws.h | 5 | ||||
-rw-r--r-- | runtime/native/java_lang_reflect_Constructor.cc | 7 | ||||
-rw-r--r-- | runtime/native/java_lang_reflect_Field.cc | 158 | ||||
-rw-r--r-- | runtime/native/java_lang_reflect_Method.cc | 8 | ||||
-rw-r--r-- | runtime/reflection.cc | 36 | ||||
-rw-r--r-- | runtime/reflection.h | 5 |
7 files changed, 162 insertions, 63 deletions
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc index 24d16c4..4b6d82b 100644 --- a/runtime/common_throws.cc +++ b/runtime/common_throws.cc @@ -175,6 +175,12 @@ void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) { va_end(args); } +// IllegalAccessException + +void ThrowIllegalAccessException(const ThrowLocation* throw_location, const char* msg) { + ThrowException(throw_location, "Ljava/lang/IllegalAccessException;", NULL, msg); +} + // IllegalArgumentException void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const char* msg) { diff --git a/runtime/common_throws.h b/runtime/common_throws.h index 792cdef..c06763e 100644 --- a/runtime/common_throws.h +++ b/runtime/common_throws.h @@ -92,6 +92,11 @@ void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR; +// IllegalAccessException + +void ThrowIllegalAccessException(const ThrowLocation* throw_location, const char* msg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR; + // IllegalArgumentException void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const char* msg) diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc index b7e8ac2..d28ebd0 100644 --- a/runtime/native/java_lang_reflect_Constructor.cc +++ b/runtime/native/java_lang_reflect_Constructor.cc @@ -34,7 +34,8 @@ namespace art { * check. We can also safely assume the constructor isn't associated * with an interface, array, or primitive class. */ -static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) { +static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs, + jboolean accessible) { ScopedFastNativeObjectAccess soa(env); mirror::ArtMethod* m = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod); SirtRef<mirror::Class> c(soa.Self(), m->GetDeclaringClass()); @@ -67,14 +68,14 @@ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectA } jobject javaReceiver = soa.AddLocalReference<jobject>(receiver); - InvokeMethod(soa, javaMethod, javaReceiver, javaArgs); + InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, accessible); // Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod. return javaReceiver; } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Constructor, newInstance, "!([Ljava/lang/Object;)Ljava/lang/Object;"), + NATIVE_METHOD(Constructor, newInstance, "!([Ljava/lang/Object;Z)Ljava/lang/Object;"), }; void register_java_lang_reflect_Constructor(JNIEnv* env) { diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc index 48b58bf..755708e 100644 --- a/runtime/native/java_lang_reflect_Field.cc +++ b/runtime/native/java_lang_reflect_Field.cc @@ -20,6 +20,7 @@ #include "dex_file-inl.h" #include "jni_internal.h" #include "mirror/art_field-inl.h" +#include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "object_utils.h" #include "reflection.h" @@ -27,6 +28,21 @@ namespace art { +static bool ValidateFieldAccess(mirror::ArtField* field, mirror::Object* obj, bool is_set) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (field->IsFinal() && is_set) { + ThrowIllegalAccessException(nullptr, StringPrintf("Cannot set final field: %s", + PrettyField(field).c_str()).c_str()); + return false; + } + if (!ValidateAccess(obj, field->GetDeclaringClass(), field->GetAccessFlags())) { + ThrowIllegalAccessException(nullptr, StringPrintf("Cannot access field: %s", + PrettyField(field).c_str()).c_str()); + return false; + } + return true; +} + static bool GetFieldValue(const ScopedFastNativeObjectAccess& soa, mirror::Object* o, mirror::ArtField* f, Primitive::Type field_type, bool allow_references, JValue* value) @@ -98,7 +114,7 @@ static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa, jobject j_rcv return true; } -static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) { +static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { ScopedFastNativeObjectAccess soa(env); CHECK(!kMovingFields) << "CheckReceiver may trigger thread suspension for initialization"; mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField); @@ -107,6 +123,11 @@ static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) { DCHECK(soa.Self()->IsExceptionPending()); return nullptr; } + // Validate access. + if (!accessible && !ValidateFieldAccess(f, o, false)) { + DCHECK(soa.Self()->IsExceptionPending()); + return nullptr; + } // We now don't expect suspension unless an exception is thrown. // Get the field's value, boxing if necessary. Primitive::Type field_type = FieldHelper(f).GetTypeAsPrimitiveType(); @@ -119,7 +140,7 @@ static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) { } static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, - char dst_descriptor) { + char dst_descriptor, jboolean accessible) { ScopedFastNativeObjectAccess soa(env); CHECK(!kMovingFields) << "CheckReceiver may trigger thread suspension for initialization"; mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField); @@ -128,6 +149,13 @@ static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, DCHECK(soa.Self()->IsExceptionPending()); return JValue(); } + + // Validate access. + if (!accessible && !ValidateFieldAccess(f, o, false)) { + DCHECK(soa.Self()->IsExceptionPending()); + return JValue(); + } + // We now don't expect suspension unless an exception is thrown. // Read the value. Primitive::Type field_type = FieldHelper(f).GetTypeAsPrimitiveType(); @@ -147,36 +175,38 @@ static JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, return wide_value; } -static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj) { - return GetPrimitiveField(env, javaField, javaObj, 'Z').GetZ(); +static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj, + jboolean accessible) { + return GetPrimitiveField(env, javaField, javaObj, 'Z', accessible).GetZ(); } -static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj) { - return GetPrimitiveField(env, javaField, javaObj, 'B').GetB(); +static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { + return GetPrimitiveField(env, javaField, javaObj, 'B', accessible).GetB(); } -static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj) { - return GetPrimitiveField(env, javaField, javaObj, 'C').GetC(); +static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { + return GetPrimitiveField(env, javaField, javaObj, 'C', accessible).GetC(); } -static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj) { - return GetPrimitiveField(env, javaField, javaObj, 'D').GetD(); +static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj, + jboolean accessible) { + return GetPrimitiveField(env, javaField, javaObj, 'D', accessible).GetD(); } -static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj) { - return GetPrimitiveField(env, javaField, javaObj, 'F').GetF(); +static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { + return GetPrimitiveField(env, javaField, javaObj, 'F', accessible).GetF(); } -static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj) { - return GetPrimitiveField(env, javaField, javaObj, 'I').GetI(); +static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { + return GetPrimitiveField(env, javaField, javaObj, 'I', accessible).GetI(); } -static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj) { - return GetPrimitiveField(env, javaField, javaObj, 'J').GetJ(); +static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { + return GetPrimitiveField(env, javaField, javaObj, 'J', accessible).GetJ(); } -static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) { - return GetPrimitiveField(env, javaField, javaObj, 'S').GetS(); +static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) { + return GetPrimitiveField(env, javaField, javaObj, 'S', accessible).GetS(); } static void SetFieldValue(ScopedFastNativeObjectAccess& soa, mirror::Object* o, @@ -223,7 +253,8 @@ static void SetFieldValue(ScopedFastNativeObjectAccess& soa, mirror::Object* o, } } -static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) { +static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue, + jboolean accessible) { ScopedFastNativeObjectAccess soa(env); CHECK(!kMovingFields) << "CheckReceiver may trigger thread suspension for initialization"; mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField); @@ -260,11 +291,16 @@ static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject j DCHECK(soa.Self()->IsExceptionPending()); return; } + // Validate access. + if (!accessible && !ValidateFieldAccess(f, o, true)) { + DCHECK(soa.Self()->IsExceptionPending()); + return; + } SetFieldValue(soa, o, f, field_prim_type, true, unboxed_value); } static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor, - const JValue& new_value) { + const JValue& new_value, jboolean accessible) { ScopedFastNativeObjectAccess soa(env); mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField); mirror::Object* o = nullptr; @@ -286,77 +322,91 @@ static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, c return; } + // Validate access. + if (!accessible && !ValidateFieldAccess(f, o, true)) { + DCHECK(soa.Self()->IsExceptionPending()); + return; + } + // Write the value. SetFieldValue(soa, o, f, field_type, false, wide_value); } -static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) { +static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z, + jboolean accessible) { JValue value; value.SetZ(z); - SetPrimitiveField(env, javaField, javaObj, 'Z', value); + SetPrimitiveField(env, javaField, javaObj, 'Z', value, accessible); } -static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b) { +static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b, + jboolean accessible) { JValue value; value.SetB(b); - SetPrimitiveField(env, javaField, javaObj, 'B', value); + SetPrimitiveField(env, javaField, javaObj, 'B', value, accessible); } -static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c) { +static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c, + jboolean accessible) { JValue value; value.SetC(c); - SetPrimitiveField(env, javaField, javaObj, 'C', value); + SetPrimitiveField(env, javaField, javaObj, 'C', value, accessible); } -static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d) { +static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d, + jboolean accessible) { JValue value; value.SetD(d); - SetPrimitiveField(env, javaField, javaObj, 'D', value); + SetPrimitiveField(env, javaField, javaObj, 'D', value, accessible); } -static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f) { +static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f, + jboolean accessible) { JValue value; value.SetF(f); - SetPrimitiveField(env, javaField, javaObj, 'F', value); + SetPrimitiveField(env, javaField, javaObj, 'F', value, accessible); } -static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i) { +static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i, + jboolean accessible) { JValue value; value.SetI(i); - SetPrimitiveField(env, javaField, javaObj, 'I', value); + SetPrimitiveField(env, javaField, javaObj, 'I', value, accessible); } -static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j) { +static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j, + jboolean accessible) { JValue value; value.SetJ(j); - SetPrimitiveField(env, javaField, javaObj, 'J', value); + SetPrimitiveField(env, javaField, javaObj, 'J', value, accessible); } -static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s) { +static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s, + jboolean accessible) { JValue value; value.SetS(s); - SetPrimitiveField(env, javaField, javaObj, 'S', value); + SetPrimitiveField(env, javaField, javaObj, 'S', value, accessible); } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Field, get, "!(Ljava/lang/Object;)Ljava/lang/Object;"), - NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;)Z"), - NATIVE_METHOD(Field, getByte, "!(Ljava/lang/Object;)B"), - NATIVE_METHOD(Field, getChar, "!(Ljava/lang/Object;)C"), - NATIVE_METHOD(Field, getDouble, "!(Ljava/lang/Object;)D"), - NATIVE_METHOD(Field, getFloat, "!(Ljava/lang/Object;)F"), - NATIVE_METHOD(Field, getInt, "!(Ljava/lang/Object;)I"), - NATIVE_METHOD(Field, getLong, "!(Ljava/lang/Object;)J"), - NATIVE_METHOD(Field, getShort, "!(Ljava/lang/Object;)S"), - NATIVE_METHOD(Field, set, "!(Ljava/lang/Object;Ljava/lang/Object;)V"), - NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;Z)V"), - NATIVE_METHOD(Field, setByte, "!(Ljava/lang/Object;B)V"), - NATIVE_METHOD(Field, setChar, "!(Ljava/lang/Object;C)V"), - NATIVE_METHOD(Field, setDouble, "!(Ljava/lang/Object;D)V"), - NATIVE_METHOD(Field, setFloat, "!(Ljava/lang/Object;F)V"), - NATIVE_METHOD(Field, setInt, "!(Ljava/lang/Object;I)V"), - NATIVE_METHOD(Field, setLong, "!(Ljava/lang/Object;J)V"), - NATIVE_METHOD(Field, setShort, "!(Ljava/lang/Object;S)V"), + NATIVE_METHOD(Field, get, "!(Ljava/lang/Object;Z)Ljava/lang/Object;"), + NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;Z)Z"), + NATIVE_METHOD(Field, getByte, "!(Ljava/lang/Object;Z)B"), + NATIVE_METHOD(Field, getChar, "!(Ljava/lang/Object;Z)C"), + NATIVE_METHOD(Field, getDouble, "!(Ljava/lang/Object;Z)D"), + NATIVE_METHOD(Field, getFloat, "!(Ljava/lang/Object;Z)F"), + NATIVE_METHOD(Field, getInt, "!(Ljava/lang/Object;Z)I"), + NATIVE_METHOD(Field, getLong, "!(Ljava/lang/Object;Z)J"), + NATIVE_METHOD(Field, getShort, "!(Ljava/lang/Object;Z)S"), + NATIVE_METHOD(Field, set, "!(Ljava/lang/Object;Ljava/lang/Object;Z)V"), + NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;ZZ)V"), + NATIVE_METHOD(Field, setByte, "!(Ljava/lang/Object;BZ)V"), + NATIVE_METHOD(Field, setChar, "!(Ljava/lang/Object;CZ)V"), + NATIVE_METHOD(Field, setDouble, "!(Ljava/lang/Object;DZ)V"), + NATIVE_METHOD(Field, setFloat, "!(Ljava/lang/Object;FZ)V"), + NATIVE_METHOD(Field, setInt, "!(Ljava/lang/Object;IZ)V"), + NATIVE_METHOD(Field, setLong, "!(Ljava/lang/Object;JZ)V"), + NATIVE_METHOD(Field, setShort, "!(Ljava/lang/Object;SZ)V"), }; void register_java_lang_reflect_Field(JNIEnv* env) { diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc index abb73b6..c23f65c 100644 --- a/runtime/native/java_lang_reflect_Method.cc +++ b/runtime/native/java_lang_reflect_Method.cc @@ -29,10 +29,10 @@ namespace art { -static jobject Method_invoke(JNIEnv* env, - jobject javaMethod, jobject javaReceiver, jobject javaArgs) { +static jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiver, + jobject javaArgs, jboolean accessible) { ScopedFastNativeObjectAccess soa(env); - return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs); + return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, accessible); } static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) { @@ -56,7 +56,7 @@ static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) { } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Method, invoke, "!(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"), + NATIVE_METHOD(Method, invoke, "!(Ljava/lang/Object;[Ljava/lang/Object;Z)Ljava/lang/Object;"), NATIVE_METHOD(Method, getExceptionTypesNative, "!()[Ljava/lang/Class;"), }; diff --git a/runtime/reflection.cc b/runtime/reflection.cc index 7f39e70..b38f9b4 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -26,6 +26,7 @@ #include "mirror/class-inl.h" #include "mirror/object_array.h" #include "mirror/object_array-inl.h" +#include "nth_caller_visitor.h" #include "object_utils.h" #include "scoped_thread_state_change.h" #include "stack.h" @@ -461,7 +462,7 @@ void InvokeWithShadowFrame(Thread* self, ShadowFrame* shadow_frame, uint16_t arg } jobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod, - jobject javaReceiver, jobject javaArgs) { + jobject javaReceiver, jobject javaArgs, bool accessible) { mirror::ArtMethod* m = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod); mirror::Class* declaring_class = m->GetDeclaringClass(); @@ -499,6 +500,13 @@ jobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod, return NULL; } + // Validate access. + if (!accessible && !ValidateAccess(receiver, declaring_class, m->GetAccessFlags())) { + ThrowIllegalAccessException(nullptr, StringPrintf("Cannot access method: %s", + PrettyMethod(m).c_str()).c_str()); + return nullptr; + } + // Invoke the method. JValue result; ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); @@ -786,4 +794,30 @@ bool UnboxPrimitiveForResult(const ThrowLocation& throw_location, mirror::Object return UnboxPrimitive(&throw_location, o, dst_class, nullptr, unboxed_value); } +bool ValidateAccess(mirror::Object* obj, mirror::Class* declaring_class, uint32_t access_flags) { + NthCallerVisitor visitor(Thread::Current(), 2); + visitor.WalkStack(); + mirror::Class* caller_class = visitor.caller->GetDeclaringClass(); + + if (((access_flags & kAccPublic) && declaring_class->IsPublic()) || + caller_class == declaring_class) { + return true; + } + if (access_flags & kAccPrivate) { + return false; + } + if (access_flags & kAccProtected) { + if (obj != nullptr && !obj->InstanceOf(caller_class) && + !declaring_class->IsInSamePackage(caller_class)) { + return false; + } else if (declaring_class->IsAssignableFrom(caller_class)) { + return true; + } + } + if (!declaring_class->IsInSamePackage(caller_class)) { + return false; + } + return true; +} + } // namespace art diff --git a/runtime/reflection.h b/runtime/reflection.h index 325998f..5cc725f 100644 --- a/runtime/reflection.h +++ b/runtime/reflection.h @@ -68,12 +68,15 @@ void InvokeWithShadowFrame(Thread* self, ShadowFrame* shadow_frame, uint16_t arg SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); jobject InvokeMethod(const ScopedObjectAccess& soa, jobject method, jobject receiver, - jobject args) + jobject args, bool accessible) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); +bool ValidateAccess(mirror::Object* obj, mirror::Class* declaring_class, uint32_t access_flags) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + } // namespace art #endif // ART_RUNTIME_REFLECTION_H_ |