summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--oatdump/oatdump.cc2
-rw-r--r--runtime/Android.mk1
-rw-r--r--runtime/class_linker.cc45
-rw-r--r--runtime/class_linker.h2
-rw-r--r--runtime/class_linker_test.cc31
-rw-r--r--runtime/debugger.cc2
-rw-r--r--runtime/interpreter/interpreter_common.cc2
-rw-r--r--runtime/interpreter/unstarted_runtime.cc19
-rw-r--r--runtime/jni_internal.cc18
-rw-r--r--runtime/mirror/accessible_object.h60
-rw-r--r--runtime/mirror/art_field-inl.h36
-rw-r--r--runtime/mirror/art_field.h10
-rw-r--r--runtime/mirror/field-inl.h79
-rw-r--r--runtime/mirror/field.cc64
-rw-r--r--runtime/mirror/field.h145
-rw-r--r--runtime/mirror/object.cc4
-rw-r--r--runtime/mirror/object.h2
-rw-r--r--runtime/mirror/reference.h2
-rw-r--r--runtime/native/java_lang_Class.cc169
-rw-r--r--runtime/native/java_lang_reflect_Field.cc256
-rw-r--r--runtime/proxy_test.cc4
-rw-r--r--runtime/reflection-inl.h12
-rw-r--r--runtime/reflection.cc24
-rw-r--r--runtime/reflection.h5
-rw-r--r--runtime/runtime.cc2
-rw-r--r--runtime/verifier/method_verifier.cc4
-rw-r--r--runtime/well_known_classes.cc2
-rw-r--r--runtime/well_known_classes.h1
-rw-r--r--test/046-reflect/src/Main.java9
29 files changed, 796 insertions, 216 deletions
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 7bde471..322d3aa 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1597,7 +1597,7 @@ class ImageDumper {
os << StringPrintf("null %s\n", PrettyDescriptor(field->GetTypeDescriptor()).c_str());
} else {
// Grab the field type without causing resolution.
- mirror::Class* field_type = field->GetType(false);
+ mirror::Class* field_type = field->GetType<false>();
if (field_type != nullptr) {
PrettyObjectValue(os, field_type, value);
} else {
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 5548d94..dde5407 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -103,6 +103,7 @@ LIBART_COMMON_SRC_FILES := \
mirror/array.cc \
mirror/class.cc \
mirror/dex_cache.cc \
+ mirror/field.cc \
mirror/object.cc \
mirror/reference.cc \
mirror/stack_trace_element.cc \
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 7521266..a89196d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -56,6 +56,7 @@
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
+#include "mirror/field.h"
#include "mirror/iftable-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
@@ -313,7 +314,7 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
java_lang_String->SetObjectSize(mirror::String::InstanceSize());
mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusResolved, self);
- // Setup Reference.
+ // Setup java.lang.ref.Reference.
Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize())));
mirror::Reference::SetClass(java_lang_ref_Reference.Get());
@@ -321,7 +322,7 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusResolved, self);
// Create storage for root classes, save away our work so far (requires descriptors).
- class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class> >(
+ class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.Get(),
kClassRootsMax));
CHECK(!class_roots_.IsNull());
@@ -531,6 +532,19 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
mirror::Class* java_lang_reflect_Proxy = FindSystemClass(self, "Ljava/lang/reflect/Proxy;");
SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy);
+ // Create java.lang.reflect.Field.class root.
+ mirror::Class* java_lang_reflect_Field = FindSystemClass(self, "Ljava/lang/reflect/Field;");
+ CHECK(java_lang_reflect_Field != nullptr);
+ SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
+ mirror::Field::SetClass(java_lang_reflect_Field);
+
+ // Create java.lang.reflect.Field array root.
+ mirror::Class* java_lang_reflect_Field_array =
+ FindSystemClass(self, "[Ljava/lang/reflect/Field;");
+ CHECK(java_lang_reflect_Field_array != nullptr);
+ SetClassRoot(kJavaLangReflectFieldArrayClass, java_lang_reflect_Field_array);
+ mirror::Field::SetArrayClass(java_lang_reflect_Field_array);
+
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
// finish initializing Reference class
mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self);
@@ -818,9 +832,10 @@ void ClassLinker::InitFromImage() {
VLOG(startup) << "ClassLinker::InitFromImage entering";
CHECK(!init_done_);
- Thread* self = Thread::Current();
- gc::Heap* heap = Runtime::Current()->GetHeap();
- gc::space::ImageSpace* space = heap->GetImageSpace();
+ Runtime* const runtime = Runtime::Current();
+ Thread* const self = Thread::Current();
+ gc::Heap* const heap = runtime->GetHeap();
+ gc::space::ImageSpace* const space = heap->GetImageSpace();
dex_cache_image_class_lookup_required_ = true;
CHECK(space != nullptr);
OatFile& oat_file = GetImageOatFile(space);
@@ -875,7 +890,7 @@ void ClassLinker::InitFromImage() {
// bitmap walk.
mirror::ArtMethod::SetClass(GetClassRoot(kJavaLangReflectArtMethod));
size_t art_method_object_size = mirror::ArtMethod::GetJavaLangReflectArtMethod()->GetObjectSize();
- if (!Runtime::Current()->IsAotCompiler()) {
+ if (!runtime->IsAotCompiler()) {
// Aot compiler supports having an image with a different pointer size than the runtime. This
// happens on the host for compile 32 bit tests since we use a 64 bit libart compiler. We may
// also use 32 bit dex2oat on a system with 64 bit apps.
@@ -890,7 +905,6 @@ void ClassLinker::InitFromImage() {
}
// Set entry point to interpreter if in InterpretOnly mode.
- Runtime* runtime = Runtime::Current();
if (!runtime->IsAotCompiler() && runtime->GetInstrumentation()->InterpretOnly()) {
heap->VisitObjects(InitFromImageInterpretOnlyCallback, this);
}
@@ -903,6 +917,8 @@ void ClassLinker::InitFromImage() {
array_iftable_ = GcRoot<mirror::IfTable>(GetClassRoot(kObjectArrayClass)->GetIfTable());
DCHECK_EQ(array_iftable_.Read(), GetClassRoot(kBooleanArrayClass)->GetIfTable());
// String class root was set above
+ mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField));
+ mirror::Field::SetArrayClass(GetClassRoot(kJavaLangReflectFieldArrayClass));
mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference));
mirror::ArtField::SetClass(GetClassRoot(kJavaLangReflectArtField));
mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
@@ -1088,6 +1104,8 @@ ClassLinker::~ClassLinker() {
mirror::Reference::ResetClass();
mirror::ArtField::ResetClass();
mirror::ArtMethod::ResetClass();
+ mirror::Field::ResetClass();
+ mirror::Field::ResetArrayClass();
mirror::BooleanArray::ResetArrayClass();
mirror::ByteArray::ResetArrayClass();
mirror::CharArray::ResetArrayClass();
@@ -5189,10 +5207,12 @@ const char* ClassLinker::GetClassRootDescriptor(ClassRoot class_root) {
"Ljava/lang/ref/Reference;",
"Ljava/lang/reflect/ArtField;",
"Ljava/lang/reflect/ArtMethod;",
+ "Ljava/lang/reflect/Field;",
"Ljava/lang/reflect/Proxy;",
"[Ljava/lang/String;",
"[Ljava/lang/reflect/ArtField;",
"[Ljava/lang/reflect/ArtMethod;",
+ "[Ljava/lang/reflect/Field;",
"Ljava/lang/ClassLoader;",
"Ljava/lang/Throwable;",
"Ljava/lang/ClassNotFoundException;",
@@ -5311,14 +5331,11 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi
Handle<mirror::ArtField> h_dex_elements_field =
hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements));
- mirror::Class* dex_elements_class = h_dex_elements_field->GetType(true);
+ mirror::Class* dex_elements_class = h_dex_elements_field->GetType<true>();
DCHECK(dex_elements_class != nullptr);
DCHECK(dex_elements_class->IsArrayClass());
- Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements =
- hs.NewHandle(reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(
- mirror::Array::Alloc<true>(self, dex_elements_class, dex_files.size(),
- dex_elements_class->GetComponentSizeShift(),
- Runtime::Current()->GetHeap()->GetCurrentAllocator())));
+ Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements(hs.NewHandle(
+ mirror::ObjectArray<mirror::Object>::Alloc(self, dex_elements_class, dex_files.size())));
Handle<mirror::Class> h_dex_element_class =
hs.NewHandle(dex_elements_class->GetComponentType());
@@ -5329,7 +5346,7 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi
Handle<mirror::ArtField> h_cookie_field =
hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie));
- DCHECK_EQ(h_cookie_field->GetDeclaringClass(), h_element_file_field->GetType(false));
+ DCHECK_EQ(h_cookie_field->GetDeclaringClass(), h_element_file_field->GetType<false>());
// Fill the elements array.
int32_t index = 0;
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 88a2501..ec984cb 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -72,10 +72,12 @@ class ClassLinker {
kJavaLangRefReference,
kJavaLangReflectArtField,
kJavaLangReflectArtMethod,
+ kJavaLangReflectField,
kJavaLangReflectProxy,
kJavaLangStringArrayClass,
kJavaLangReflectArtFieldArrayClass,
kJavaLangReflectArtMethodArrayClass,
+ kJavaLangReflectFieldArrayClass,
kJavaLangClassLoader,
kJavaLangThrowable,
kJavaLangClassNotFoundException,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index a895a49..3e727e7 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -24,11 +24,13 @@
#include "dex_file.h"
#include "entrypoints/entrypoint_utils-inl.h"
#include "gc/heap.h"
+#include "mirror/accessible_object.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
+#include "mirror/field.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/proxy.h"
@@ -177,7 +179,7 @@ class ClassLinkerTest : public CommonRuntimeTest {
EXPECT_TRUE(field->GetClass() != nullptr);
EXPECT_EQ(klass, field->GetDeclaringClass());
EXPECT_TRUE(field->GetName() != nullptr);
- EXPECT_TRUE(field->GetType(true) != nullptr);
+ EXPECT_TRUE(field->GetType<true>() != nullptr);
}
void AssertClass(const std::string& descriptor, Handle<mirror::Class> klass)
@@ -283,7 +285,7 @@ class ClassLinkerTest : public CommonRuntimeTest {
for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
mirror::ArtField* field = klass->GetInstanceField(i);
fhandle.Assign(field);
- mirror::Class* field_type = fhandle->GetType(true);
+ mirror::Class* field_type = fhandle->GetType<true>();
ASSERT_TRUE(field_type != nullptr);
if (!field->IsPrimitiveType()) {
ASSERT_TRUE(!field_type->IsPrimitive());
@@ -394,7 +396,12 @@ struct CheckOffsets {
// Art method have a different size due to the padding field.
if (!klass->IsArtMethodClass() && !klass->IsClassClass() && !is_static) {
- size_t expected_size = is_static ? klass->GetClassSize(): klass->GetObjectSize();
+ // Currently only required for AccessibleObject since of the padding fields. The class linker
+ // says AccessibleObject is 9 bytes but sizeof(AccessibleObject) is 12 bytes due to padding.
+ // The RoundUp is to get around this case.
+ static constexpr size_t kPackAlignment = 4;
+ size_t expected_size = RoundUp(is_static ? klass->GetClassSize(): klass->GetObjectSize(),
+ kPackAlignment);
if (sizeof(T) != expected_size) {
LOG(ERROR) << "Class size mismatch:"
<< " class=" << class_descriptor
@@ -596,6 +603,22 @@ struct FinalizerReferenceOffsets : public CheckOffsets<mirror::FinalizerReferenc
};
};
+struct AccessibleObjectOffsets : public CheckOffsets<mirror::AccessibleObject> {
+ AccessibleObjectOffsets() : CheckOffsets<mirror::AccessibleObject>(false, "Ljava/lang/reflect/AccessibleObject;") {
+ offsets.push_back(CheckOffset(mirror::AccessibleObject::FlagOffset().Uint32Value(), "flag"));
+ };
+};
+
+struct FieldOffsets : public CheckOffsets<mirror::Field> {
+ FieldOffsets() : CheckOffsets<mirror::Field>(false, "Ljava/lang/reflect/Field;") {
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, access_flags_), "accessFlags"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, declaring_class_), "declaringClass"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, dex_field_index_), "dexFieldIndex"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, offset_), "offset"));
+ offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, type_), "type"));
+ };
+};
+
// C++ fields must exactly match the fields in the Java classes. If this fails,
// reorder the fields in the C++ class. Managed class fields are ordered by
// ClassLinker::LinkFields.
@@ -613,6 +636,8 @@ TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) {
EXPECT_TRUE(DexCacheOffsets().Check());
EXPECT_TRUE(ReferenceOffsets().Check());
EXPECT_TRUE(FinalizerReferenceOffsets().Check());
+ EXPECT_TRUE(AccessibleObjectOffsets().Check());
+ EXPECT_TRUE(FieldOffsets().Check());
}
TEST_F(ClassLinkerTest, FindClassNonexistent) {
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index a1ae236..5ea0187 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -1798,7 +1798,7 @@ static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId
HandleWrapper<mirror::Object> h_v(hs.NewHandleWrapper(&v));
HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o));
- field_type = h_f->GetType(true);
+ field_type = h_f->GetType<true>();
}
if (!field_type->IsAssignableFrom(v->GetClass())) {
return JDWP::ERR_INVALID_OBJECT;
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index a3ab026..a310452 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -285,7 +285,7 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction
HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
HandleWrapper<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
- field_class = h_f->GetType(true);
+ field_class = h_f->GetType<true>();
}
if (!reg->VerifierInstanceOf(field_class)) {
// This should never happen.
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 98dfdbd..1b08e80 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -29,6 +29,7 @@
#include "mirror/array-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class.h"
+#include "mirror/field-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
@@ -219,19 +220,11 @@ static void UnstartedClassGetDeclaredField(
PrettyDescriptor(klass).c_str());
return;
}
- // TODO: getDeclaredField calls GetType once the field is found to ensure a
- // NoClassDefFoundError is thrown if the field's type cannot be resolved.
- mirror::Class* jlr_Field = self->DecodeJObject(
- WellKnownClasses::java_lang_reflect_Field)->AsClass();
- StackHandleScope<1> hs(self);
- Handle<mirror::Object> field(hs.NewHandle(jlr_Field->AllocNonMovableObject(self)));
- CHECK(field.Get() != nullptr);
- mirror::ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>",
- "(Ljava/lang/reflect/ArtField;)V");
- uint32_t args[1];
- args[0] = StackReference<mirror::Object>::FromMirrorPtr(found).AsVRegValue();
- EnterInterpreterFromInvoke(self, c, field.Get(), args, nullptr);
- result->SetL(field.Get());
+ if (Runtime::Current()->IsActiveTransaction()) {
+ result->SetL(mirror::Field::CreateFromArtField<true>(self, found, true));
+ } else {
+ result->SetL(mirror::Field::CreateFromArtField<false>(self, found, true));
+ }
}
static void UnstartedVmClassLoaderFindLoadedClass(
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 9a71ba4..5e38470 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -41,6 +41,7 @@
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
+#include "mirror/field.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
@@ -346,7 +347,13 @@ class JNI {
static jfieldID FromReflectedField(JNIEnv* env, jobject jlr_field) {
CHECK_NON_NULL_ARGUMENT(jlr_field);
ScopedObjectAccess soa(env);
- return soa.EncodeField(mirror::ArtField::FromReflectedField(soa, jlr_field));
+ mirror::Object* obj_field = soa.Decode<mirror::Object*>(jlr_field);
+ if (obj_field->GetClass() != mirror::Field::StaticClass()) {
+ // Not even a java.lang.reflect.Field, return nullptr.
+ return nullptr;
+ }
+ auto* field = static_cast<mirror::Field*>(obj_field);
+ return soa.EncodeField(field->GetArtField());
}
static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
@@ -373,14 +380,7 @@ class JNI {
CHECK_NON_NULL_ARGUMENT(fid);
ScopedObjectAccess soa(env);
mirror::ArtField* f = soa.DecodeField(fid);
- ScopedLocalRef<jobject> art_field(env, soa.AddLocalReference<jobject>(f));
- jobject reflect_field = env->AllocObject(WellKnownClasses::java_lang_reflect_Field);
- if (env->ExceptionCheck()) {
- return nullptr;
- }
- SetObjectField(env, reflect_field,
- WellKnownClasses::java_lang_reflect_Field_artField, art_field.get());
- return reflect_field;
+ return soa.AddLocalReference<jobject>(mirror::Field::CreateFromArtField(soa.Self(), f, true));
}
static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
diff --git a/runtime/mirror/accessible_object.h b/runtime/mirror/accessible_object.h
new file mode 100644
index 0000000..6d4c0f6
--- /dev/null
+++ b/runtime/mirror/accessible_object.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_ACCESSIBLE_OBJECT_H_
+#define ART_RUNTIME_MIRROR_ACCESSIBLE_OBJECT_H_
+
+#include "class.h"
+#include "gc_root.h"
+#include "object.h"
+#include "object_callbacks.h"
+#include "read_barrier_option.h"
+#include "thread.h"
+
+namespace art {
+
+namespace mirror {
+
+// C++ mirror of java.lang.reflect.AccessibleObject
+class MANAGED AccessibleObject : public Object {
+ public:
+ static MemberOffset FlagOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(AccessibleObject, flag_);
+ }
+
+ template<bool kTransactionActive>
+ void SetAccessible(bool value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ UNUSED(padding_);
+ return SetFieldBoolean<kTransactionActive>(FlagOffset(), value ? 1u : 0u);
+ }
+
+ bool IsAccessible() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldBoolean(FlagOffset());
+ }
+
+ private:
+ uint8_t flag_;
+ // Padding required for now since "packed" will cause reflect.Field fields to not be aligned
+ // otherwise.
+ uint8_t padding_[3];
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AccessibleObject);
+};
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_ACCESSIBLE_OBJECT_H_
diff --git a/runtime/mirror/art_field-inl.h b/runtime/mirror/art_field-inl.h
index 2b406bd..986852f 100644
--- a/runtime/mirror/art_field-inl.h
+++ b/runtime/mirror/art_field-inl.h
@@ -34,7 +34,7 @@ namespace art {
namespace mirror {
inline uint32_t ArtField::ClassSize() {
- uint32_t vtable_entries = Object::kVTableLength + 6;
+ uint32_t vtable_entries = Object::kVTableLength;
return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
}
@@ -290,16 +290,19 @@ inline bool ArtField::IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_loc
return GetTypeAsPrimitiveType() != Primitive::kPrimNot;
}
-inline Class* ArtField::GetType(bool resolve) {
- uint32_t field_index = GetDexFieldIndex();
- if (UNLIKELY(GetDeclaringClass()->IsProxyClass())) {
+template <bool kResolve>
+inline Class* ArtField::GetType() {
+ const uint32_t field_index = GetDexFieldIndex();
+ auto* declaring_class = GetDeclaringClass();
+ if (UNLIKELY(declaring_class->IsProxyClass())) {
return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(),
GetTypeDescriptor());
}
- const DexFile* dex_file = GetDexFile();
+ auto* dex_cache = declaring_class->GetDexCache();
+ const DexFile* const dex_file = dex_cache->GetDexFile();
const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
- mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
- if (resolve && (type == nullptr)) {
+ mirror::Class* type = dex_cache->GetResolvedType(field_id.type_idx_);
+ if (kResolve && UNLIKELY(type == nullptr)) {
type = Runtime::Current()->GetClassLinker()->ResolveType(field_id.type_idx_, this);
CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
}
@@ -318,12 +321,19 @@ inline const DexFile* ArtField::GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutato
return GetDexCache()->GetDexFile();
}
-inline ArtField* ArtField::FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa,
- jobject jlr_field) {
- mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_reflect_Field_artField);
- mirror::ArtField* field = f->GetObject(soa.Decode<mirror::Object*>(jlr_field))->AsArtField();
- DCHECK(field != nullptr);
- return field;
+inline String* ArtField::GetStringName(Thread* self, bool resolve) {
+ auto dex_field_index = GetDexFieldIndex();
+ CHECK_NE(dex_field_index, DexFile::kDexNoIndex);
+ auto* dex_cache = GetDexCache();
+ const auto* dex_file = dex_cache->GetDexFile();
+ const auto& field_id = dex_file->GetFieldId(dex_field_index);
+ auto* name = dex_cache->GetResolvedString(field_id.name_idx_);
+ if (resolve && name == nullptr) {
+ StackHandleScope<1> hs(self);
+ name = Runtime::Current()->GetClassLinker()->ResolveString(
+ *dex_file, field_id.name_idx_, hs.NewHandle(dex_cache));
+ }
+ return name;
}
} // namespace mirror
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index a1d8844..d640165 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -47,10 +47,6 @@ class MANAGED ArtField FINAL : public Object {
return sizeof(ArtField);
}
- ALWAYS_INLINE static ArtField* FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa,
- jobject jlr_field)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -155,13 +151,17 @@ class MANAGED ArtField FINAL : public Object {
const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Resolves / returns the name from the dex cache.
+ String* GetStringName(Thread* self, bool resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Primitive::Type GetTypeAsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Class* GetType(bool resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template <bool kResolve>
+ Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
new file mode 100644
index 0000000..24ebc48
--- /dev/null
+++ b/runtime/mirror/field-inl.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_FIELD_INL_H_
+#define ART_RUNTIME_MIRROR_FIELD_INL_H_
+
+#include "field.h"
+
+#include "art_field-inl.h"
+#include "runtime-inl.h"
+
+namespace art {
+
+namespace mirror {
+
+template <bool kTransactionActive>
+inline mirror::Field* Field::CreateFromArtField(Thread* self, mirror::ArtField* field,
+ bool force_resolve) {
+ CHECK(!kMovingFields);
+ // Try to resolve type before allocating since this is a thread suspension point.
+ mirror::Class* type = field->GetType<true>();
+
+ if (type == nullptr) {
+ if (force_resolve) {
+ if (kIsDebugBuild) {
+ self->AssertPendingException();
+ }
+ return nullptr;
+ } else {
+ // Can't resolve, clear the exception if it isn't OOME and continue with a null type.
+ mirror::Throwable* exception = self->GetException();
+ if (exception->GetClass()->DescriptorEquals("Ljava/lang/OutOfMemoryError;")) {
+ return nullptr;
+ }
+ self->ClearException();
+ }
+ }
+ StackHandleScope<1> hs(self);
+ auto ret = hs.NewHandle(static_cast<Field*>(StaticClass()->AllocObject(self)));
+ if (ret.Get() == nullptr) {
+ if (kIsDebugBuild) {
+ self->AssertPendingException();
+ }
+ return nullptr;
+ }
+ auto dex_field_index = field->GetDexFieldIndex();
+ auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index);
+ if (resolved_field != nullptr) {
+ DCHECK_EQ(resolved_field, field);
+ } else {
+ // We rely on the field being resolved so that we can back to the ArtField
+ // (i.e. FromReflectedMethod).
+ field->GetDexCache()->SetResolvedField(dex_field_index, field);
+ }
+ ret->SetType<kTransactionActive>(type);
+ ret->SetDeclaringClass<kTransactionActive>(field->GetDeclaringClass());
+ ret->SetAccessFlags<kTransactionActive>(field->GetAccessFlags());
+ ret->SetDexFieldIndex<kTransactionActive>(dex_field_index);
+ ret->SetOffset<kTransactionActive>(field->GetOffset().Int32Value());
+ return ret.Get();
+}
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_FIELD_INL_H_
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
new file mode 100644
index 0000000..1724682
--- /dev/null
+++ b/runtime/mirror/field.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "field-inl.h"
+
+#include "dex_cache-inl.h"
+#include "object_array-inl.h"
+#include "object-inl.h"
+
+namespace art {
+namespace mirror {
+
+GcRoot<Class> Field::static_class_;
+GcRoot<Class> Field::array_class_;
+
+void Field::SetClass(Class* klass) {
+ CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+ CHECK(klass != nullptr);
+ static_class_ = GcRoot<Class>(klass);
+}
+
+void Field::ResetClass() {
+ CHECK(!static_class_.IsNull());
+ static_class_ = GcRoot<Class>(nullptr);
+}
+
+void Field::SetArrayClass(Class* klass) {
+ CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
+ CHECK(klass != nullptr);
+ array_class_ = GcRoot<Class>(klass);
+}
+
+void Field::ResetArrayClass() {
+ CHECK(!array_class_.IsNull());
+ array_class_ = GcRoot<Class>(nullptr);
+}
+
+void Field::VisitRoots(RootCallback* callback, void* arg) {
+ static_class_.VisitRootIfNonNull(callback, arg, RootInfo(kRootStickyClass));
+ array_class_.VisitRootIfNonNull(callback, arg, RootInfo(kRootStickyClass));
+}
+
+ArtField* Field::GetArtField() {
+ mirror::DexCache* const dex_cache = GetDeclaringClass()->GetDexCache();
+ mirror::ArtField* const art_field = dex_cache->GetResolvedField(GetDexFieldIndex());
+ CHECK(art_field != nullptr);
+ return art_field;
+}
+
+} // namespace mirror
+} // namespace art
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
new file mode 100644
index 0000000..f54340a
--- /dev/null
+++ b/runtime/mirror/field.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_FIELD_H_
+#define ART_RUNTIME_MIRROR_FIELD_H_
+
+#include "accessible_object.h"
+#include "gc_root.h"
+#include "object.h"
+#include "object_callbacks.h"
+#include "read_barrier_option.h"
+
+namespace art {
+
+struct FieldOffsets;
+
+namespace mirror {
+
+class ArtField;
+class Class;
+class String;
+
+// C++ mirror of java.lang.reflect.Field.
+class MANAGED Field : public AccessibleObject {
+ public:
+ static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return static_class_.Read();
+ }
+
+ static mirror::Class* ArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return array_class_.Read();
+ }
+
+ ALWAYS_INLINE uint32_t GetDexFieldIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, dex_field_index_));
+ }
+
+ mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_));
+ }
+
+ uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_));
+ }
+
+ bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return (GetAccessFlags() & kAccStatic) != 0;
+ }
+
+ bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return (GetAccessFlags() & kAccFinal) != 0;
+ }
+
+ bool IsVolatile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return (GetAccessFlags() & kAccVolatile) != 0;
+ }
+
+ ALWAYS_INLINE Primitive::Type GetTypeAsPrimitiveType()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetType()->GetPrimitiveType();
+ }
+
+ mirror::Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetFieldObject<mirror::Class>(OFFSET_OF_OBJECT_MEMBER(Field, type_));
+ }
+
+ int32_t GetOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_));
+ }
+
+ static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void VisitRoots(RootCallback* callback, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Slow, try to use only for PrettyField and such.
+ mirror::ArtField* GetArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ template <bool kTransactionActive = false>
+ static mirror::Field* CreateFromArtField(Thread* self, mirror::ArtField* field,
+ bool force_resolve)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ HeapReference<mirror::Class> declaring_class_;
+ HeapReference<mirror::Class> type_;
+ int32_t access_flags_;
+ int32_t dex_field_index_;
+ int32_t offset_;
+
+ template<bool kTransactionActive>
+ void SetDeclaringClass(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c);
+ }
+
+ template<bool kTransactionActive>
+ void SetType(mirror::Class* type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, type_), type);
+ }
+
+ template<bool kTransactionActive>
+ void SetAccessFlags(uint32_t flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), flags);
+ }
+
+ template<bool kTransactionActive>
+ void SetDexFieldIndex(uint32_t idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, dex_field_index_), idx);
+ }
+
+ template<bool kTransactionActive>
+ void SetOffset(uint32_t offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SetField32<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, offset_), offset);
+ }
+
+ static GcRoot<Class> static_class_; // java.lang.reflect.Field.class.
+ static GcRoot<Class> array_class_; // array of java.lang.reflect.Field.
+
+ friend struct art::FieldOffsets; // for verifying offset information
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Field);
+};
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_FIELD_H_
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index bbbdf98..57ac46f 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -214,7 +214,7 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val
if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
// TODO: resolve the field type for moving GC.
- mirror::Class* field_type = field->GetType(!kMovingCollector);
+ mirror::Class* field_type = field->GetType<!kMovingCollector>();
if (field_type != nullptr) {
CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
}
@@ -236,7 +236,7 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val
if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
// TODO: resolve the field type for moving GC.
- mirror::Class* field_type = field->GetType(!kMovingCollector);
+ mirror::Class* field_type = field->GetType<!kMovingCollector>();
if (field_type != nullptr) {
CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
}
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 780c5ae..b730670 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -100,7 +100,7 @@ class MANAGED LOCKABLE Object {
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool VerifierInstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ALWAYS_INLINE bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
diff --git a/runtime/mirror/reference.h b/runtime/mirror/reference.h
index 7345448..69ef69c 100644
--- a/runtime/mirror/reference.h
+++ b/runtime/mirror/reference.h
@@ -99,7 +99,7 @@ class MANAGED Reference : public Object {
return java_lang_ref_Reference_.Read<kReadBarrierOption>();
}
static void SetClass(Class* klass);
- static void ResetClass(void);
+ static void ResetClass();
static void VisitRoots(RootCallback* callback, void* arg);
private:
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 60d14e9..3cb6b36 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -17,21 +17,28 @@
#include "java_lang_Class.h"
#include "class_linker.h"
+#include "common_throws.h"
#include "dex_file-inl.h"
#include "jni_internal.h"
#include "nth_caller_visitor.h"
+#include "mirror/art_field-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
+#include "mirror/field.h"
#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/string-inl.h"
#include "scoped_thread_state_change.h"
#include "scoped_fast_native_object_access.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
+#include "utf.h"
#include "well_known_classes.h"
namespace art {
-static mirror::Class* DecodeClass(const ScopedFastNativeObjectAccess& soa, jobject java_class)
+ALWAYS_INLINE static inline mirror::Class* DecodeClass(
+ const ScopedFastNativeObjectAccess& soa, jobject java_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
DCHECK(c != NULL);
@@ -97,10 +104,170 @@ static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
}
+static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
+ Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ StackHandleScope<3> hs(self);
+ auto h_ifields = hs.NewHandle(klass->GetIFields());
+ auto h_sfields = hs.NewHandle(klass->GetSFields());
+ const int32_t num_ifields = h_ifields.Get() != nullptr ? h_ifields->GetLength() : 0;
+ const int32_t num_sfields = h_sfields.Get() != nullptr ? h_sfields->GetLength() : 0;
+ int32_t array_size = num_ifields + num_sfields;
+ if (public_only) {
+ // Lets go subtract all the non public fields.
+ for (int32_t i = 0; i < num_ifields; ++i) {
+ if (!h_ifields->GetWithoutChecks(i)->IsPublic()) {
+ --array_size;
+ }
+ }
+ for (int32_t i = 0; i < num_sfields; ++i) {
+ if (!h_sfields->GetWithoutChecks(i)->IsPublic()) {
+ --array_size;
+ }
+ }
+ }
+ int32_t array_idx = 0;
+ auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc(
+ self, mirror::Field::ArrayClass(), array_size));
+ if (object_array.Get() == nullptr) {
+ return nullptr;
+ }
+ for (int32_t i = 0; i < num_ifields; ++i) {
+ auto* art_field = h_ifields->GetWithoutChecks(i);
+ if (!public_only || art_field->IsPublic()) {
+ auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
+ if (field == nullptr) {
+ if (kIsDebugBuild) {
+ self->AssertPendingException();
+ }
+ // Maybe null due to OOME or type resolving exception.
+ return nullptr;
+ }
+ object_array->SetWithoutChecks<false>(array_idx++, field);
+ }
+ }
+ for (int32_t i = 0; i < num_sfields; ++i) {
+ auto* art_field = h_sfields->GetWithoutChecks(i);
+ if (!public_only || art_field->IsPublic()) {
+ auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
+ if (field == nullptr) {
+ if (kIsDebugBuild) {
+ self->AssertPendingException();
+ }
+ return nullptr;
+ }
+ object_array->SetWithoutChecks<false>(array_idx++, field);
+ }
+ }
+ CHECK_EQ(array_idx, array_size);
+ return object_array.Get();
+}
+
+static jobjectArray Class_getDeclaredFieldsUnchecked(JNIEnv* env, jobject javaThis,
+ jboolean publicOnly) {
+ ScopedFastNativeObjectAccess soa(env);
+ return soa.AddLocalReference<jobjectArray>(
+ GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), publicOnly != JNI_FALSE, false));
+}
+
+static jobjectArray Class_getDeclaredFields(JNIEnv* env, jobject javaThis) {
+ ScopedFastNativeObjectAccess soa(env);
+ return soa.AddLocalReference<jobjectArray>(
+ GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), false, true));
+}
+
+static jobjectArray Class_getPublicDeclaredFields(JNIEnv* env, jobject javaThis) {
+ ScopedFastNativeObjectAccess soa(env);
+ return soa.AddLocalReference<jobjectArray>(
+ GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), true, true));
+}
+
+// Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use
+// the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
+// fast.
+ALWAYS_INLINE static inline mirror::ArtField* FindFieldByName(
+ Thread* self ATTRIBUTE_UNUSED, mirror::String* name,
+ mirror::ObjectArray<mirror::ArtField>* fields)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uint32_t low = 0;
+ uint32_t high = fields->GetLength();
+ const uint16_t* const data = name->GetCharArray()->GetData() + name->GetOffset();
+ const size_t length = name->GetLength();
+ while (low < high) {
+ auto mid = (low + high) / 2;
+ mirror::ArtField* const field = fields->GetWithoutChecks(mid);
+ int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field->GetName(), data, length);
+ // Alternate approach, only a few % faster at the cost of more allocations.
+ // int result = field->GetStringName(self, true)->CompareTo(name);
+ if (result < 0) {
+ low = mid + 1;
+ } else if (result > 0) {
+ high = mid;
+ } else {
+ return field;
+ }
+ }
+ if (kIsDebugBuild) {
+ for (int32_t i = 0; i < fields->GetLength(); ++i) {
+ CHECK_NE(fields->GetWithoutChecks(i)->GetName(), name->ToModifiedUtf8());
+ }
+ }
+ return nullptr;
+}
+
+ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(
+ Thread* self, mirror::Class* c, mirror::String* name)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ auto* instance_fields = c->GetIFields();
+ if (instance_fields != nullptr) {
+ auto* art_field = FindFieldByName(self, name, instance_fields);
+ if (art_field != nullptr) {
+ return mirror::Field::CreateFromArtField(self, art_field, true);
+ }
+ }
+ auto* static_fields = c->GetSFields();
+ if (static_fields != nullptr) {
+ auto* art_field = FindFieldByName(self, name, static_fields);
+ if (art_field != nullptr) {
+ return mirror::Field::CreateFromArtField(self, art_field, true);
+ }
+ }
+ return nullptr;
+}
+
+static jobject Class_getDeclaredFieldInternal(JNIEnv* env, jobject javaThis, jstring name) {
+ ScopedFastNativeObjectAccess soa(env);
+ auto* name_string = soa.Decode<mirror::String*>(name);
+ return soa.AddLocalReference<jobject>(
+ GetDeclaredField(soa.Self(), DecodeClass(soa, javaThis), name_string));
+}
+
+static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
+ ScopedFastNativeObjectAccess soa(env);
+ auto* name_string = soa.Decode<mirror::String*>(name);
+ if (name == nullptr) {
+ ThrowNullPointerException("name == null");
+ return nullptr;
+ }
+ auto* klass = DecodeClass(soa, javaThis);
+ mirror::Field* result = GetDeclaredField(soa.Self(), klass, name_string);
+ if (result == nullptr) {
+ std::string name_str = name_string->ToModifiedUtf8();
+ soa.Self()->ThrowNewException("Ljava/lang/NoSuchFieldException;", name_str.c_str());
+ return nullptr;
+ }
+ return soa.AddLocalReference<jobject>(result);
+}
+
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
+ NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
};
void register_java_lang_Class(JNIEnv* env) {
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 9c5bde9..0fe78b3 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -21,23 +21,23 @@
#include "common_throws.h"
#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 "mirror/field.h"
#include "reflection-inl.h"
#include "scoped_fast_native_object_access.h"
namespace art {
template<bool kIsSet>
-ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::ArtField* field,
+ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::Field* field,
mirror::Object* obj)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (kIsSet && field->IsFinal()) {
ThrowIllegalAccessException(
StringPrintf("Cannot set %s field %s of class %s",
PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
- PrettyField(field).c_str(),
+ PrettyField(field->GetArtField()).c_str(),
field->GetDeclaringClass() == nullptr ? "null" :
PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
return false;
@@ -49,7 +49,7 @@ ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::ArtFiel
StringPrintf("Class %s cannot access %s field %s of class %s",
calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
- PrettyField(field).c_str(),
+ PrettyField(field->GetArtField()).c_str(),
field->GetDeclaringClass() == nullptr ? "null" :
PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
return false;
@@ -58,38 +58,37 @@ ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::ArtFiel
}
template<bool kAllowReferences>
-ALWAYS_INLINE inline static bool GetFieldValue(mirror::Object* o, mirror::ArtField* f,
+ALWAYS_INLINE inline static bool GetFieldValue(mirror::Object* o, mirror::Field* f,
Primitive::Type field_type, JValue* value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_EQ(value->GetJ(), INT64_C(0));
+ MemberOffset offset(f->GetOffset());
+ const bool is_volatile = f->IsVolatile();
switch (field_type) {
case Primitive::kPrimBoolean:
- value->SetZ(f->GetBoolean(o));
+ value->SetZ(is_volatile ? o->GetFieldBooleanVolatile(offset) : o->GetFieldBoolean(offset));
return true;
case Primitive::kPrimByte:
- value->SetB(f->GetByte(o));
+ value->SetB(is_volatile ? o->GetFieldByteVolatile(offset) : o->GetFieldByte(offset));
return true;
case Primitive::kPrimChar:
- value->SetC(f->GetChar(o));
- return true;
- case Primitive::kPrimDouble:
- value->SetD(f->GetDouble(o));
- return true;
- case Primitive::kPrimFloat:
- value->SetF(f->GetFloat(o));
+ value->SetC(is_volatile ? o->GetFieldCharVolatile(offset) : o->GetFieldChar(offset));
return true;
case Primitive::kPrimInt:
- value->SetI(f->GetInt(o));
+ case Primitive::kPrimFloat:
+ value->SetI(is_volatile ? o->GetField32Volatile(offset) : o->GetField32(offset));
return true;
case Primitive::kPrimLong:
- value->SetJ(f->GetLong(o));
+ case Primitive::kPrimDouble:
+ value->SetJ(is_volatile ? o->GetField64Volatile(offset) : o->GetField64(offset));
return true;
case Primitive::kPrimShort:
- value->SetS(f->GetShort(o));
+ value->SetS(is_volatile ? o->GetFieldShortVolatile(offset) : o->GetFieldShort(offset));
return true;
case Primitive::kPrimNot:
if (kAllowReferences) {
- value->SetL(f->GetObject(o));
+ value->SetL(is_volatile ? o->GetFieldObjectVolatile<mirror::Object>(offset) :
+ o->GetFieldObject<mirror::Object>(offset));
return true;
}
// Else break to report an error.
@@ -98,23 +97,23 @@ ALWAYS_INLINE inline static bool GetFieldValue(mirror::Object* o, mirror::ArtFie
// Never okay.
break;
}
- ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
- PrettyField(f).c_str()).c_str());
+ ThrowIllegalArgumentException(
+ StringPrintf("Not a primitive field: %s", PrettyField(f->GetArtField()).c_str()).c_str());
return false;
}
ALWAYS_INLINE inline static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa,
- jobject j_rcvr, mirror::ArtField** f,
+ jobject j_rcvr, mirror::Field** f,
mirror::Object** class_or_rcvr)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
soa.Self()->AssertThreadSuspensionIsAllowable();
mirror::Class* declaringClass = (*f)->GetDeclaringClass();
if ((*f)->IsStatic()) {
if (UNLIKELY(!declaringClass->IsInitialized())) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<2> hs(soa.Self());
- HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(f));
+ HandleWrapper<mirror::Field> h_f(hs.NewHandleWrapper(f));
HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&declaringClass));
+ ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
if (UNLIKELY(!class_linker->EnsureInitialized(soa.Self(), h_klass, true, true))) {
DCHECK(soa.Self()->IsExceptionPending());
return false;
@@ -131,16 +130,16 @@ ALWAYS_INLINE inline static bool CheckReceiver(const ScopedFastNativeObjectAcces
return true;
}
-static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
+static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+ mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
DCHECK(soa.Self()->IsExceptionPending());
return nullptr;
}
// If field is not set to be accessible, verify it can be accessed by the caller.
- if ((accessible == JNI_FALSE) && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
+ if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
DCHECK(soa.Self()->IsExceptionPending());
return nullptr;
}
@@ -157,9 +156,9 @@ static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj, jboole
template<Primitive::Type kPrimitiveType>
ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaField,
- jobject javaObj, jboolean accessible) {
+ jobject javaObj) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+ mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
DCHECK(soa.Self()->IsExceptionPending());
@@ -167,7 +166,7 @@ ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaFi
}
// If field is not set to be accessible, verify it can be accessed by the caller.
- if (accessible == JNI_FALSE && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
+ if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
DCHECK(soa.Self()->IsExceptionPending());
return JValue();
}
@@ -198,72 +197,97 @@ ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaFi
return wide_value;
}
-static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj,
- jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, accessible).GetZ();
+static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj).GetZ();
}
-static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, accessible).GetB();
+static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj).GetB();
}
-static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, accessible).GetC();
+static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj).GetC();
}
-static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj,
- jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, accessible).GetD();
+static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj).GetD();
}
-static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, accessible).GetF();
+static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj).GetF();
}
-static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, accessible).GetI();
+static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj).GetI();
}
-static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, accessible).GetJ();
+static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj).GetJ();
}
-static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj, jboolean accessible) {
- return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, accessible).GetS();
+static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) {
+ return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj).GetS();
}
-static void SetFieldValue(mirror::Object* o, mirror::ArtField* f, Primitive::Type field_type,
- bool allow_references, const JValue& new_value)
+ALWAYS_INLINE inline static void SetFieldValue(mirror::Object* o, mirror::Field* f,
+ Primitive::Type field_type, bool allow_references,
+ const JValue& new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(f->GetDeclaringClass()->IsInitialized());
+ MemberOffset offset(f->GetOffset());
+ const bool is_volatile = f->IsVolatile();
switch (field_type) {
case Primitive::kPrimBoolean:
- f->SetBoolean<false>(o, new_value.GetZ());
+ if (is_volatile) {
+ o->SetFieldBooleanVolatile<false>(offset, new_value.GetZ());
+ } else {
+ o->SetFieldBoolean<false>(offset, new_value.GetZ());
+ }
break;
case Primitive::kPrimByte:
- f->SetByte<false>(o, new_value.GetB());
+ if (is_volatile) {
+ o->SetFieldBooleanVolatile<false>(offset, new_value.GetB());
+ } else {
+ o->SetFieldBoolean<false>(offset, new_value.GetB());
+ }
break;
case Primitive::kPrimChar:
- f->SetChar<false>(o, new_value.GetC());
- break;
- case Primitive::kPrimDouble:
- f->SetDouble<false>(o, new_value.GetD());
- break;
- case Primitive::kPrimFloat:
- f->SetFloat<false>(o, new_value.GetF());
+ if (is_volatile) {
+ o->SetFieldBooleanVolatile<false>(offset, new_value.GetC());
+ } else {
+ o->SetFieldBoolean<false>(offset, new_value.GetC());
+ }
break;
case Primitive::kPrimInt:
- f->SetInt<false>(o, new_value.GetI());
+ case Primitive::kPrimFloat:
+ if (is_volatile) {
+ o->SetField32Volatile<false>(offset, new_value.GetI());
+ } else {
+ o->SetField32<false>(offset, new_value.GetI());
+ }
break;
case Primitive::kPrimLong:
- f->SetLong<false>(o, new_value.GetJ());
+ case Primitive::kPrimDouble:
+ if (is_volatile) {
+ o->SetField64Volatile<false>(offset, new_value.GetJ());
+ } else {
+ o->SetField64<false>(offset, new_value.GetJ());
+ }
break;
case Primitive::kPrimShort:
- f->SetShort<false>(o, new_value.GetS());
+ if (is_volatile) {
+ o->SetFieldShortVolatile<false>(offset, new_value.GetZ());
+ } else {
+ o->SetFieldShort<false>(offset, new_value.GetZ());
+ }
break;
case Primitive::kPrimNot:
if (allow_references) {
- f->SetObject<false>(o, new_value.GetL());
+ if (is_volatile) {
+ o->SetFieldObjectVolatile<false>(offset, new_value.GetL());
+ } else {
+ o->SetFieldObject<false>(offset, new_value.GetL());
+ }
break;
}
// Else fall through to report an error.
@@ -271,15 +295,14 @@ static void SetFieldValue(mirror::Object* o, mirror::ArtField* f, Primitive::Typ
case Primitive::kPrimVoid:
// Never okay.
ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
- PrettyField(f).c_str()).c_str());
+ PrettyField(f->GetArtField()).c_str()).c_str());
return;
}
}
-static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue,
- jboolean accessible) {
+static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+ mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
// Check that the receiver is non-null and an instance of the field's declaring class.
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
@@ -287,18 +310,11 @@ static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject j
return;
}
mirror::Class* field_type;
- const char* field_type_desciptor = f->GetTypeDescriptor();
+ const char* field_type_desciptor = f->GetArtField()->GetTypeDescriptor();
Primitive::Type field_prim_type = Primitive::GetType(field_type_desciptor[0]);
if (field_prim_type == Primitive::kPrimNot) {
- StackHandleScope<2> hs(soa.Self());
- HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o));
- HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
- // May cause resolution.
- field_type = h_f->GetType(true);
- if (field_type == nullptr) {
- DCHECK(soa.Self()->IsExceptionPending());
- return;
- }
+ field_type = f->GetType();
+ DCHECK(field_type != nullptr);
} else {
field_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(field_type_desciptor[0]);
}
@@ -306,12 +322,12 @@ static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject j
// Unbox the value, if necessary.
mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
JValue unboxed_value;
- if (!UnboxPrimitiveForField(boxed_value, field_type, f, &unboxed_value)) {
+ if (!UnboxPrimitiveForField(boxed_value, field_type, f->GetArtField(), &unboxed_value)) {
DCHECK(soa.Self()->IsExceptionPending());
return;
}
// If field is not set to be accessible, verify it can be accessed by the caller.
- if ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
+ if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
DCHECK(soa.Self()->IsExceptionPending());
return;
}
@@ -320,9 +336,9 @@ static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject j
template<Primitive::Type kPrimitiveType>
static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
- const JValue& new_value, jboolean accessible) {
+ const JValue& new_value) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ArtField* f = mirror::ArtField::FromReflectedField(soa, javaField);
+ mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
return;
@@ -330,7 +346,7 @@ static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
Primitive::Type field_type = f->GetTypeAsPrimitiveType();
if (UNLIKELY(field_type == Primitive::kPrimNot)) {
ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
- PrettyField(f).c_str()).c_str());
+ PrettyField(f->GetArtField()).c_str()).c_str());
return;
}
@@ -342,7 +358,7 @@ static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
}
// If field is not set to be accessible, verify it can be accessed by the caller.
- if ((accessible == JNI_FALSE) && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
+ if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
DCHECK(soa.Self()->IsExceptionPending());
return;
}
@@ -351,81 +367,73 @@ static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
SetFieldValue(o, f, field_type, false, wide_value);
}
-static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z,
- jboolean accessible) {
+static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) {
JValue value;
value.SetZ(z);
- SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value);
}
-static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b,
- jboolean accessible) {
+static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b) {
JValue value;
value.SetB(b);
- SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value);
}
-static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c,
- jboolean accessible) {
+static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c) {
JValue value;
value.SetC(c);
- SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value);
}
-static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d,
- jboolean accessible) {
+static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d) {
JValue value;
value.SetD(d);
- SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value);
}
-static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f,
- jboolean accessible) {
+static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f) {
JValue value;
value.SetF(f);
- SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value);
}
-static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i,
- jboolean accessible) {
+static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i) {
JValue value;
value.SetI(i);
- SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value);
}
-static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j,
- jboolean accessible) {
+static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j) {
JValue value;
value.SetJ(j);
- SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value);
}
-static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s,
- jboolean accessible) {
+static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s) {
JValue value;
value.SetS(s);
- SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value, accessible);
+ SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value);
}
static JNINativeMethod gMethods[] = {
- 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"),
+ 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"),
};
void register_java_lang_reflect_Field(JNIEnv* env) {
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 3260992..cb97049 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -185,7 +185,7 @@ TEST_F(ProxyTest, ProxyFieldHelper) {
MutableHandle<mirror::ArtField> fhandle = hs.NewHandle(static_fields->Get(0));
EXPECT_EQ("interfaces", std::string(fhandle->GetName()));
EXPECT_EQ("[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor()));
- EXPECT_EQ(interfacesFieldClass.Get(), fhandle->GetType(true));
+ EXPECT_EQ(interfacesFieldClass.Get(), fhandle->GetType<true>());
std::string temp;
EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp)));
EXPECT_FALSE(fhandle->IsPrimitiveType());
@@ -194,7 +194,7 @@ TEST_F(ProxyTest, ProxyFieldHelper) {
fhandle.Assign(static_fields->Get(1));
EXPECT_EQ("throws", std::string(fhandle->GetName()));
EXPECT_EQ("[[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor()));
- EXPECT_EQ(throwsFieldClass.Get(), fhandle->GetType(true));
+ EXPECT_EQ(throwsFieldClass.Get(), fhandle->GetType<true>());
EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp)));
EXPECT_FALSE(fhandle->IsPrimitiveType());
}
diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h
index f21c1a0..f54d4ca 100644
--- a/runtime/reflection-inl.h
+++ b/runtime/reflection-inl.h
@@ -22,6 +22,7 @@
#include "base/stringprintf.h"
#include "common_throws.h"
#include "jvalue.h"
+#include "mirror/object-inl.h"
#include "primitive.h"
#include "utils.h"
@@ -99,6 +100,17 @@ inline bool ConvertPrimitiveValue(bool unbox_for_result,
return false;
}
+inline bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) {
+ if (UNLIKELY(o == nullptr)) {
+ ThrowNullPointerException("null receiver");
+ return false;
+ } else if (UNLIKELY(!o->InstanceOf(c))) {
+ InvalidReceiverError(o, c);
+ return false;
+ }
+ return true;
+}
+
} // namespace art
#endif // ART_RUNTIME_REFLECTION_INL_H_
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index a54a39d..d845e40 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -24,7 +24,6 @@
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
-#include "mirror/class.h"
#include "mirror/object_array-inl.h"
#include "mirror/object_array.h"
#include "nth_caller_visitor.h"
@@ -628,21 +627,6 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM
return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
}
-bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) {
- if (o == nullptr) {
- ThrowNullPointerException("null receiver");
- return false;
- } else if (!o->InstanceOf(c)) {
- std::string expected_class_name(PrettyDescriptor(c));
- std::string actual_class_name(PrettyTypeOf(o));
- ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s",
- expected_class_name.c_str(),
- actual_class_name.c_str()).c_str());
- return false;
- }
- return true;
-}
-
mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) {
if (src_class == Primitive::kPrimNot) {
return value.GetL();
@@ -840,4 +824,12 @@ bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_cl
return declaring_class->IsInSamePackage(caller_class);
}
+void InvalidReceiverError(mirror::Object* o, mirror::Class* c) {
+ std::string expected_class_name(PrettyDescriptor(c));
+ std::string actual_class_name(PrettyTypeOf(o));
+ ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s",
+ expected_class_name.c_str(),
+ actual_class_name.c_str()).c_str());
+}
+
} // namespace art
diff --git a/runtime/reflection.h b/runtime/reflection.h
index 857d63b..6bef664 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -69,13 +69,16 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject metho
jobject args, bool accessible)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c)
+ALWAYS_INLINE bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
uint32_t access_flags, mirror::Class** calling_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+void InvalidReceiverError(mirror::Object* o, mirror::Class* c)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
} // namespace art
#endif // ART_RUNTIME_REFLECTION_H_
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c462153..d7dd6d0 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -75,6 +75,7 @@
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
+#include "mirror/field.h"
#include "mirror/stack_trace_element.h"
#include "mirror/throwable.h"
#include "monitor.h"
@@ -1291,6 +1292,7 @@ void Runtime::VisitConstantRoots(RootCallback* callback, void* arg) {
mirror::StackTraceElement::VisitRoots(callback, arg);
mirror::String::VisitRoots(callback, arg);
mirror::Throwable::VisitRoots(callback, arg);
+ mirror::Field::VisitRoots(callback, arg);
// Visit all the primitive array types classes.
mirror::PrimitiveArray<uint8_t>::VisitRoots(callback, arg); // BooleanArray
mirror::PrimitiveArray<int8_t>::VisitRoots(callback, arg); // ByteArray
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 988fc0e..1d04192 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3919,7 +3919,7 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType&
{
StackHandleScope<1> hs(self_);
HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field));
- field_type_class = h_field->GetType(can_load_classes_);
+ field_type_class = can_load_classes_ ? h_field->GetType<true>() : h_field->GetType<false>();
}
if (field_type_class != nullptr) {
field_type = &reg_types_.FromClass(field->GetTypeDescriptor(), field_type_class,
@@ -4035,7 +4035,7 @@ void MethodVerifier::VerifyQuickFieldAccess(const Instruction* inst, const RegTy
{
StackHandleScope<1> hs(Thread::Current());
HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field));
- field_type_class = h_field->GetType(can_load_classes_);
+ field_type_class = can_load_classes_ ? h_field->GetType<true>() : h_field->GetType<false>();
}
if (field_type_class != nullptr) {
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 00b4cef..d389244 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -109,7 +109,6 @@ jfieldID WellKnownClasses::java_lang_Throwable_stackTrace;
jfieldID WellKnownClasses::java_lang_Throwable_stackState;
jfieldID WellKnownClasses::java_lang_Throwable_suppressedExceptions;
jfieldID WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod;
-jfieldID WellKnownClasses::java_lang_reflect_Field_artField;
jfieldID WellKnownClasses::java_lang_reflect_Proxy_h;
jfieldID WellKnownClasses::java_nio_DirectByteBuffer_capacity;
jfieldID WellKnownClasses::java_nio_DirectByteBuffer_effectiveDirectAddress;
@@ -244,7 +243,6 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_Throwable_stackState = CacheField(env, java_lang_Throwable, false, "stackState", "Ljava/lang/Object;");
java_lang_Throwable_suppressedExceptions = CacheField(env, java_lang_Throwable, false, "suppressedExceptions", "Ljava/util/List;");
java_lang_reflect_AbstractMethod_artMethod = CacheField(env, java_lang_reflect_AbstractMethod, false, "artMethod", "Ljava/lang/reflect/ArtMethod;");
- java_lang_reflect_Field_artField = CacheField(env, java_lang_reflect_Field, false, "artField", "Ljava/lang/reflect/ArtField;");
java_lang_reflect_Proxy_h = CacheField(env, java_lang_reflect_Proxy, false, "h", "Ljava/lang/reflect/InvocationHandler;");
java_nio_DirectByteBuffer_capacity = CacheField(env, java_nio_DirectByteBuffer, false, "capacity", "I");
java_nio_DirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_DirectByteBuffer, false, "effectiveDirectAddress", "J");
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 1a4f0f8..2df1c0e 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -103,7 +103,6 @@ struct WellKnownClasses {
static jfieldID dalvik_system_DexPathList__Element_dexFile;
static jfieldID dalvik_system_PathClassLoader_pathList;
static jfieldID java_lang_reflect_AbstractMethod_artMethod;
- static jfieldID java_lang_reflect_Field_artField;
static jfieldID java_lang_reflect_Proxy_h;
static jfieldID java_lang_Thread_daemon;
static jfieldID java_lang_Thread_group;
diff --git a/test/046-reflect/src/Main.java b/test/046-reflect/src/Main.java
index 3fe3881..5c6ca13 100644
--- a/test/046-reflect/src/Main.java
+++ b/test/046-reflect/src/Main.java
@@ -696,22 +696,25 @@ public class Main {
private static void checkGetDeclaredConstructor() {
try {
Method.class.getDeclaredConstructor().setAccessible(true);
- System.out.print("Didn't get an exception from method getDeclaredConstructor");
+ System.out.print("Didn't get an exception from Method.class.getDeclaredConstructor().setAccessible");
+ } catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (Exception e) {
System.out.print(e);
}
try {
Field.class.getDeclaredConstructor().setAccessible(true);
- System.out.print("Didn't get an exception from field getDeclaredConstructor");
+ System.out.print("Didn't get an exception from Field.class.getDeclaredConstructor().setAccessible");
+ } catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (Exception e) {
System.out.print(e);
}
try {
Class.class.getDeclaredConstructor().setAccessible(true);
- System.out.print("Didn't get an exception from class getDeclaredConstructor()");
+ System.out.print("Didn't get an exception from Class.class.getDeclaredConstructor().setAccessible");
} catch (SecurityException e) {
+ } catch (NoSuchMethodException e) {
} catch (Exception e) {
System.out.print(e);
}