Implement Class.getDeclared(Constructors|Fields|Methods).
This required making sure that a Method* that represents a constructor
has java.lang.reflect.Constructor as its class.
Change-Id: I25908845a2b8d686d5404ac584693db0edd5853c
diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc
index ae44b83..0a5868b 100644
--- a/src/calling_convention_arm.cc
+++ b/src/calling_convention_arm.cc
@@ -106,7 +106,7 @@
size_t padding = 0;
size_t check = method->IsStatic() ? 1 : 0;
for(size_t i = 0; i < method->NumArgs(); i++) {
- if(((i & 1) == check) && method->IsParamALongOrDouble(i)) {
+ if (((i & 1) == check) && method->IsParamALongOrDouble(i)) {
padding += 4;
}
}
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 6daa27a..1c25f61 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -78,6 +78,7 @@
"[Ljava/lang/Class;",
"[Ljava/lang/Object;",
"Ljava/lang/String;",
+ "Ljava/lang/reflect/Constructor;",
"Ljava/lang/reflect/Field;",
"Ljava/lang/reflect/Method;",
"Ljava/lang/ClassLoader;",
@@ -252,7 +253,14 @@
RegisterDexFile(*dex_file);
}
- // Field and Method are necessary so that FindClass can link members
+ // Constructor, Field, and Method are necessary so that FindClass can link members
+ Class* java_lang_reflect_Constructor = AllocClass(java_lang_Class, sizeof(MethodClass));
+ java_lang_reflect_Constructor->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Constructor;"));
+ CHECK(java_lang_reflect_Constructor != NULL);
+ java_lang_reflect_Constructor->SetObjectSize(sizeof(Method));
+ SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor);
+ java_lang_reflect_Constructor->SetStatus(Class::kStatusResolved);
+
Class* java_lang_reflect_Field = AllocClass(java_lang_Class, sizeof(FieldClass));
CHECK(java_lang_reflect_Field != NULL);
java_lang_reflect_Field->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Field;"));
@@ -262,13 +270,12 @@
Field::SetClass(java_lang_reflect_Field);
Class* java_lang_reflect_Method = AllocClass(java_lang_Class, sizeof(MethodClass));
- java_lang_reflect_Method->SetDescriptor(
- intern_table_->InternStrong("Ljava/lang/reflect/Method;"));
+ java_lang_reflect_Method->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Method;"));
CHECK(java_lang_reflect_Method != NULL);
java_lang_reflect_Method->SetObjectSize(sizeof(Method));
SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method);
java_lang_reflect_Method->SetStatus(Class::kStatusResolved);
- Method::SetClass(java_lang_reflect_Method);
+ Method::SetClasses(java_lang_reflect_Constructor, java_lang_reflect_Method);
// now we can use FindSystemClass
@@ -337,11 +344,15 @@
CHECK_EQ(java_lang_Cloneable, object_array_class->GetInterface(0));
CHECK_EQ(java_io_Serializable, object_array_class->GetInterface(1));
- // run Class, Field, and Method through FindSystemClass.
+ // run Class, Constructor, Field, and Method through FindSystemClass.
// this initializes their dex_cache_ fields and register them in classes_.
Class* Class_class = FindSystemClass("Ljava/lang/Class;");
CHECK_EQ(java_lang_Class, Class_class);
+ java_lang_reflect_Constructor->SetStatus(Class::kStatusNotReady);
+ Class* Constructor_class = FindSystemClass("Ljava/lang/reflect/Constructor;");
+ CHECK_EQ(java_lang_reflect_Constructor, Constructor_class);
+
java_lang_reflect_Field->SetStatus(Class::kStatusNotReady);
Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;");
CHECK_EQ(java_lang_reflect_Field, Field_class);
@@ -513,7 +524,7 @@
String::SetClass(GetClassRoot(kJavaLangString));
Field::SetClass(GetClassRoot(kJavaLangReflectField));
- Method::SetClass(GetClassRoot(kJavaLangReflectMethod));
+ Method::SetClasses(GetClassRoot(kJavaLangReflectConstructor), GetClassRoot(kJavaLangReflectMethod));
BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
CharArray::SetArrayClass(GetClassRoot(kCharArrayClass));
@@ -594,7 +605,7 @@
ClassLinker::~ClassLinker() {
String::ResetClass();
Field::ResetClass();
- Method::ResetClass();
+ Method::ResetClasses();
BooleanArray::ResetArrayClass();
ByteArray::ResetArrayClass();
CharArray::ResetArrayClass();
@@ -699,6 +710,8 @@
klass = GetClassRoot(kJavaLangClass);
} else if (descriptor == "Ljava/lang/String;") {
klass = GetClassRoot(kJavaLangString);
+ } else if (descriptor == "Ljava/lang/reflect/Constructor;") {
+ klass = GetClassRoot(kJavaLangReflectConstructor);
} else if (descriptor == "Ljava/lang/reflect/Field;") {
klass = GetClassRoot(kJavaLangReflectField);
} else if (descriptor == "Ljava/lang/reflect/Method;") {
@@ -957,7 +970,11 @@
Method* dst) {
const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_);
dst->SetDeclaringClass(klass);
- dst->SetName(ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache()));
+ String* method_name = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
+ dst->SetName(method_name);
+ if (method_name->Equals("<init>")) {
+ dst->SetClass(GetClassRoot(kJavaLangReflectConstructor));
+ }
{
int32_t utf16_length;
std::string utf8(dex_file.CreateMethodDescriptor(method_id.proto_idx_, &utf16_length));
diff --git a/src/class_linker.h b/src/class_linker.h
index 083d641..09736ce 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -317,6 +317,7 @@
kClassArrayClass,
kObjectArrayClass,
kJavaLangString,
+ kJavaLangReflectConstructor,
kJavaLangReflectField,
kJavaLangReflectMethod,
kJavaLangClassLoader,
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index c3b063c..ba67402 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -298,9 +298,9 @@
CheckOffset(size_t c, const char* j) : cpp_offset(c), java_name(j) {}
};
+template <typename T>
struct CheckOffsets {
bool instance;
- size_t size;
std::string class_descriptor;
std::vector<CheckOffset> offsets;
@@ -312,11 +312,11 @@
if (!klass->IsClassClass() && instance) {
size_t expected_size = instance ? klass->GetObjectSize() : klass->GetClassSize();
- if (size != expected_size) {
+ if (sizeof(T) != expected_size) {
LG << "Class size mismatch:"
<< " class=" << class_descriptor
- << " Java=" << klass->GetObjectSize()
- << " C++=" << expected_size;
+ << " Java=" << expected_size
+ << " C++=" << sizeof(T);
error = true;
}
}
@@ -376,10 +376,9 @@
// Note that ClassLinkerTest.ValidateFieldOrderOfJavaCppUnionClasses
// is first since if it is failing, others are unlikely to succeed.
-struct ObjectOffsets : public CheckOffsets {
+struct ObjectOffsets : public CheckOffsets<Object> {
ObjectOffsets() {
instance = true;
- size = sizeof(Object);
class_descriptor = "Ljava/lang/Object;";
// alphabetical references
@@ -390,19 +389,17 @@
};
};
-struct AccessibleObjectOffsets : public CheckOffsets {
+struct AccessibleObjectOffsets : public CheckOffsets<AccessibleObject> {
AccessibleObjectOffsets() {
instance = true;
- size = sizeof(AccessibleObject);
class_descriptor = "Ljava/lang/reflect/AccessibleObject;";
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AccessibleObject, java_flag_), "flag"));
};
};
-struct FieldOffsets : public CheckOffsets {
+struct FieldOffsets : public CheckOffsets<Field> {
FieldOffsets() {
instance = true;
- size = sizeof(Field);
class_descriptor = "Ljava/lang/reflect/Field;";
// alphabetical references
@@ -420,10 +417,9 @@
};
};
-struct MethodOffsets : public CheckOffsets {
+struct MethodOffsets : public CheckOffsets<Method> {
MethodOffsets() {
instance = true;
- size = sizeof(Method);
class_descriptor = "Ljava/lang/reflect/Method;";
// alphabetical references
@@ -472,10 +468,16 @@
};
};
-struct ClassOffsets : public CheckOffsets {
+struct ConstructorOffsets : public MethodOffsets {
+ ConstructorOffsets() : MethodOffsets() {
+ // We use Method* for both java.lang.reflect.Constructor and java.lang.reflect.Method.
+ class_descriptor = "Ljava/lang/reflect/Constructor;";
+ }
+};
+
+struct ClassOffsets : public CheckOffsets<Class> {
ClassOffsets() {
instance = true;
- size = sizeof(Class);
class_descriptor = "Ljava/lang/Class;";
// alphabetical references
@@ -511,10 +513,9 @@
};
};
-struct StringOffsets : public CheckOffsets {
+struct StringOffsets : public CheckOffsets<String> {
StringOffsets() {
instance = true;
- size = sizeof(String);
class_descriptor = "Ljava/lang/String;";
// alphabetical references
@@ -527,10 +528,9 @@
};
};
-struct ThrowableOffsets : public CheckOffsets {
+struct ThrowableOffsets : public CheckOffsets<Throwable> {
ThrowableOffsets() {
instance = true;
- size = sizeof(Throwable);
class_descriptor = "Ljava/lang/Throwable;";
// alphabetical references
@@ -542,10 +542,9 @@
};
};
-struct StackTraceElementOffsets : public CheckOffsets {
+struct StackTraceElementOffsets : public CheckOffsets<StackTraceElement> {
StackTraceElementOffsets() {
instance = true;
- size = sizeof(StackTraceElement);
class_descriptor = "Ljava/lang/StackTraceElement;";
// alphabetical references
@@ -556,10 +555,9 @@
};
};
-struct ClassLoaderOffsets : public CheckOffsets {
+struct ClassLoaderOffsets : public CheckOffsets<ClassLoader> {
ClassLoaderOffsets() {
instance = true;
- size = sizeof(ClassLoader);
class_descriptor = "Ljava/lang/ClassLoader;";
// alphabetical references
@@ -568,10 +566,9 @@
};
};
-struct BaseDexClassLoaderOffsets : public CheckOffsets {
+struct BaseDexClassLoaderOffsets : public CheckOffsets<BaseDexClassLoader> {
BaseDexClassLoaderOffsets() {
instance = true;
- size = sizeof(BaseDexClassLoader);
class_descriptor = "Ldalvik/system/BaseDexClassLoader;";
// alphabetical references
@@ -580,18 +577,16 @@
};
};
-struct PathClassLoaderOffsets : public CheckOffsets {
+struct PathClassLoaderOffsets : public CheckOffsets<PathClassLoader> {
PathClassLoaderOffsets() {
instance = true;
- size = sizeof(PathClassLoader);
class_descriptor = "Ldalvik/system/PathClassLoader;";
};
};
-struct ClassClassOffsets : public CheckOffsets {
+struct ClassClassOffsets : public CheckOffsets<ClassClass> {
ClassClassOffsets() {
instance = false;
- size = sizeof(ClassClass);
class_descriptor = "Ljava/lang/Class;";
// padding 32-bit
@@ -603,10 +598,9 @@
};
};
-struct StringClassOffsets : public CheckOffsets {
+struct StringClassOffsets : public CheckOffsets<StringClass> {
StringClassOffsets() {
instance = false;
- size = sizeof(StringClass);
class_descriptor = "Ljava/lang/String;";
// alphabetical references
@@ -621,10 +615,9 @@
};
};
-struct FieldClassOffsets : public CheckOffsets {
+struct FieldClassOffsets : public CheckOffsets<FieldClass> {
FieldClassOffsets() {
instance = false;
- size = sizeof(FieldClass);
class_descriptor = "Ljava/lang/reflect/Field;";
// alphabetical references
@@ -642,10 +635,9 @@
};
};
-struct MethodClassOffsets : public CheckOffsets {
+struct MethodClassOffsets : public CheckOffsets<MethodClass> {
MethodClassOffsets() {
instance = false;
- size = sizeof(MethodClass);
class_descriptor = "Ljava/lang/reflect/Method;";
// alphabetical references
@@ -660,6 +652,7 @@
TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) {
EXPECT_TRUE(ObjectOffsets().Check());
EXPECT_TRUE(AccessibleObjectOffsets().Check());
+ EXPECT_TRUE(ConstructorOffsets().Check());
EXPECT_TRUE(FieldOffsets().Check());
EXPECT_TRUE(MethodOffsets().Check());
EXPECT_TRUE(ClassOffsets().Check());
diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc
index 14c7e57..dbd9141 100644
--- a/src/compiler/codegen/CodegenFactory.cc
+++ b/src/compiler/codegen/CodegenFactory.cc
@@ -182,7 +182,7 @@
{
LIR* defStart;
LIR* defEnd;
- if(FPREG(rlSrc.lowReg)!=FPREG(rlSrc.highReg)) {
+ if (FPREG(rlSrc.lowReg)!=FPREG(rlSrc.highReg)) {
LOG(WARNING) << "rlSrc.lowreg:" << rlSrc.lowReg << ", rlSrc.highReg:"
<< rlSrc.highReg;
}
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index c334f04..d77e3f0 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -18,6 +18,7 @@
#include "class_linker.h"
#include "class_loader.h"
#include "object.h"
+#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -53,6 +54,107 @@
return AddLocalReference<jclass>(env, c);
}
+template<typename T>
+jobjectArray ToArray(JNIEnv* env, const char* array_class_name, const std::vector<T*>& objects) {
+ jclass array_class = env->FindClass(array_class_name);
+ jobjectArray result = env->NewObjectArray(objects.size(), array_class, NULL);
+ for (size_t i = 0; i < objects.size(); ++i) {
+ ScopedLocalRef<jobject> object(env, AddLocalReference<jobject>(env, objects[i]));
+ env->SetObjectArrayElement(result, i, object.get());
+ }
+ return result;
+}
+
+bool IsVisibleConstructor(Method* m, bool public_only) {
+ if (public_only && !m->IsPublic()) {
+ return false;
+ }
+ if (m->IsMiranda() || m->IsStatic()) {
+ return false;
+ }
+ if (m->GetName()->CharAt(0) != '<') {
+ return false;
+ }
+ m->InitJavaFields();
+ return true;
+}
+
+jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+ Class* c = Decode<Class*>(env, javaClass);
+
+ std::vector<Method*> constructors;
+ for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
+ Method* m = c->GetDirectMethod(i);
+ if (IsVisibleConstructor(m, publicOnly)) {
+ constructors.push_back(m);
+ }
+ }
+
+ return ToArray(env, "java/lang/reflect/Constructor", constructors);
+}
+
+bool IsVisibleField(Field* f, bool public_only) {
+ if (public_only && ~f->IsPublic()) {
+ return false;
+ }
+ f->InitJavaFields();
+ return true;
+}
+
+jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+ Class* c = Decode<Class*>(env, javaClass);
+
+ std::vector<Field*> fields;
+ for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
+ Field* f = c->GetInstanceField(i);
+ if (IsVisibleField(f, publicOnly)) {
+ fields.push_back(f);
+ }
+ }
+ for (size_t i = 0; i < c->NumStaticFields(); ++i) {
+ Field* f = c->GetStaticField(i);
+ if (IsVisibleField(f, publicOnly)) {
+ fields.push_back(f);
+ }
+ }
+
+ return ToArray(env, "java/lang/reflect/Field", fields);
+}
+
+bool IsVisibleMethod(Method* m, bool public_only) {
+ if (public_only && !m->IsPublic()) {
+ return false;
+ }
+ if (m->IsMiranda()) {
+ return false;
+ }
+ if (m->GetName()->CharAt(0) == '<') {
+ return false;
+ }
+ m->InitJavaFields();
+ return true;
+}
+
+jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+ Class* c = Decode<Class*>(env, javaClass);
+
+ std::vector<Method*> methods;
+ for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
+ Method* m = c->GetVirtualMethod(i);
+ if (IsVisibleMethod(m, publicOnly)) {
+ methods.push_back(m);
+ }
+ }
+ for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
+ Method* m = c->GetDirectMethod(i);
+ if (IsVisibleMethod(m, publicOnly)) {
+ methods.push_back(m);
+ }
+ }
+
+ return ToArray(env, "java/lang/reflect/Method", methods);
+}
+
jboolean Class_desiredAssertionStatus(JNIEnv* env, jobject javaThis) {
return JNI_FALSE;
}
@@ -115,15 +217,17 @@
String* name = Decode<String*>(env, jname);
DCHECK(name->IsString());
- for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+ for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
Field* f = klass->GetInstanceField(i);
if (f->GetName()->Equals(name)) {
+ f->InitJavaFields();
return AddLocalReference<jclass>(env, f);
}
}
for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
Field* f = klass->GetStaticField(i);
if (f->GetName()->Equals(name)) {
+ f->InitJavaFields();
return AddLocalReference<jclass>(env, f);
}
}
@@ -319,10 +423,10 @@
NATIVE_METHOD(Class, getClassLoader, "(Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
NATIVE_METHOD(Class, getComponentType, "()Ljava/lang/Class;"),
NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
- //NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
+ NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
NATIVE_METHOD(Class, getDeclaredField, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;"),
- //NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
- //NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
+ NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
NATIVE_METHOD(Class, getDeclaringClass, "()Ljava/lang/Class;"),
//NATIVE_METHOD(Class, getEnclosingClass, "()Ljava/lang/Class;"),
NATIVE_METHOD(Class, getEnclosingConstructor, "()Ljava/lang/reflect/Constructor;"),
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 96b3b34..8bc5081 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -341,9 +341,7 @@
name, class_descriptor.c_str());
return NULL;
}
- // Check invariant that all jfieldIDs have resolved types (how else would
- // the type equality in Find...Field hold?)
- DCHECK(field->GetType() != NULL);
+ field->InitJavaFields();
return EncodeField(field);
}
diff --git a/src/object.cc b/src/object.cc
index 7b47d9f..f47f16e 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -103,8 +103,24 @@
}
Class* Field::GetType() const {
- // Do full linkage (which sets dex cache value to speed next call)
- return Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
+ if (type_ == NULL) {
+ type_ = Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
+ }
+ return type_;
+}
+
+void Field::InitJavaFields() {
+ Thread* self = Thread::Current();
+ ScopedThreadStateChange tsc(self, Thread::kRunnable);
+ MonitorEnter(self);
+ if (type_ == NULL) {
+ InitJavaFieldsLocked();
+ }
+ MonitorExit(self);
+}
+
+void Field::InitJavaFieldsLocked() {
+ GetType(); // Sets type_ as a side-effect. May throw.
}
Field* Field::FindInstanceFieldFromCode(uint32_t field_idx, const Method* referrer) {
@@ -308,15 +324,23 @@
}
// TODO: get global references for these
+Class* Method::java_lang_reflect_Constructor_ = NULL;
Class* Method::java_lang_reflect_Method_ = NULL;
-void Method::SetClass(Class* java_lang_reflect_Method) {
+void Method::SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method) {
+ CHECK(java_lang_reflect_Constructor_ == NULL);
+ CHECK(java_lang_reflect_Constructor != NULL);
+ java_lang_reflect_Constructor_ = java_lang_reflect_Constructor;
+
CHECK(java_lang_reflect_Method_ == NULL);
CHECK(java_lang_reflect_Method != NULL);
java_lang_reflect_Method_ = java_lang_reflect_Method;
}
-void Method::ResetClass() {
+void Method::ResetClasses() {
+ CHECK(java_lang_reflect_Constructor_ != NULL);
+ java_lang_reflect_Constructor_ = NULL;
+
CHECK(java_lang_reflect_Method_ != NULL);
java_lang_reflect_Method_ = NULL;
}
@@ -648,7 +672,7 @@
!iter.HasNext(); iter.Next()) {
uint32_t iter_type_idx = iter.Get().type_idx_;
// Catch all case
- if(iter_type_idx == DexFile::kDexNoIndex) {
+ if (iter_type_idx == DexFile::kDexNoIndex) {
return iter.Get().address_;
}
// Does this catch exception type apply?
@@ -1186,6 +1210,19 @@
return Alloc(array_class, component_count, array_class->GetComponentSize());
}
+bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const {
+ Thread::Current()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
+ "length=%i; index=%i", length_, index);
+ return false;
+}
+
+bool Array::ThrowArrayStoreException(Object* object) const {
+ Thread::Current()->ThrowNewException("Ljava/lang/ArrayStoreException;",
+ "Can't store an element of type %s into an array of type %s",
+ PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str());
+ return false;
+}
+
template<typename T>
PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) {
DCHECK(array_class_ != NULL);
diff --git a/src/object.h b/src/object.h
index 69f8c14..ba8aaa9 100644
--- a/src/object.h
+++ b/src/object.h
@@ -442,12 +442,16 @@
false);
}
+ bool IsPublic() const {
+ return (GetAccessFlags() & kAccPublic) != 0;
+ }
+
bool IsStatic() const {
return (GetAccessFlags() & kAccStatic) != 0;
}
bool IsFinal() const {
- return (access_flags_ & kAccFinal) != 0;
+ return (GetAccessFlags() & kAccFinal) != 0;
}
uint32_t GetTypeIdx() const;
@@ -524,6 +528,8 @@
return (GetAccessFlags() & kAccVolatile) != 0;
}
+ void InitJavaFields();
+
private:
// private implementation of field access using raw data
uint32_t Get32(const Object* object) const;
@@ -533,6 +539,8 @@
Object* GetObj(const Object* object) const;
void SetObj(Object* object, const Object* new_value) const;
+ void InitJavaFieldsLocked();
+
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
// The class in which this field is declared.
@@ -543,7 +551,7 @@
const String* name_;
// Type of the field
- Class* type_;
+ mutable Class* type_;
uint32_t generic_types_are_initialized_;
@@ -642,17 +650,18 @@
return (GetAccessFlags() & synchonized) != 0;
}
- // Returns true if the method is declared final.
bool IsFinal() const {
return (GetAccessFlags() & kAccFinal) != 0;
}
- // Returns true if the method is declared native.
+ bool IsMiranda() const {
+ return (GetAccessFlags() & kAccMiranda) != 0;
+ }
+
bool IsNative() const {
return (GetAccessFlags() & kAccNative) != 0;
}
- // Returns true if the method is declared abstract.
bool IsAbstract() const {
return (GetAccessFlags() & kAccAbstract) != 0;
}
@@ -947,14 +956,17 @@
// Find the catch block for the given exception type and dex_pc
uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc) const;
- static Class* GetJavaLangReflectMethod() {
- DCHECK(java_lang_reflect_Method_ != NULL);
+ static void SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method);
+
+ static Class* GetConstructorClass() {
+ return java_lang_reflect_Constructor_;
+ }
+
+ static Class* GetMethodClass() {
return java_lang_reflect_Method_;
}
- static void SetClass(Class* java_lang_reflect_Method);
- static Class* GetMethodClass() { return java_lang_reflect_Method_; }
- static void ResetClass();
+ static void ResetClasses();
void InitJavaFields();
@@ -1079,6 +1091,7 @@
uint32_t java_slot_;
+ static Class* java_lang_reflect_Constructor_;
static Class* java_lang_reflect_Method_;
friend class ImageWriter; // for relocating code_ and invoke_stub_
@@ -1125,14 +1138,15 @@
protected:
bool IsValidIndex(int32_t index) const {
if (index < 0 || index >= length_) {
- Thread* self = Thread::Current();
- self->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
- "length=%i; index=%i", length_, index);
- return false;
+ return ThrowArrayIndexOutOfBoundsException(index);
}
return true;
}
+ protected:
+ bool ThrowArrayIndexOutOfBoundsException(int32_t index) const;
+ bool ThrowArrayStoreException(Object* object) const;
+
private:
// The number of array elements.
int32_t length_;
@@ -2097,10 +2111,8 @@
}
inline bool Object::IsMethod() const {
- Class* java_lang_Class = GetClass()->GetClass();
- Class* java_lang_reflect_Method =
- java_lang_Class->GetDirectMethod(0)->GetClass();
- return GetClass() == java_lang_reflect_Method;
+ Class* c = GetClass();
+ return c == Method::GetMethodClass() || c == Method::GetConstructorClass();
}
inline bool Object::IsReferenceInstance() const {
@@ -2209,9 +2221,10 @@
if (IsValidIndex(i)) {
if (object != NULL) {
Class* element_class = GetClass()->GetComponentType();
- DCHECK(!element_class->IsPrimitive());
- // TODO: ArrayStoreException
- CHECK(object->InstanceOf(element_class));
+ if (!object->InstanceOf(element_class)) {
+ ThrowArrayStoreException(object);
+ return;
+ }
}
MemberOffset data_offset(DataOffset().Int32Value() + i * sizeof(Object*));
SetFieldObject(data_offset, object, false);
@@ -2251,8 +2264,10 @@
CHECK(!element_class->IsPrimitive());
for (size_t i=0; i < length; i++) {
Object* object = src->GetFieldObject<Object*>(src_offset, false);
- // TODO: ArrayStoreException
- CHECK(object == NULL || object->InstanceOf(element_class));
+ if (object != NULL && !object->InstanceOf(element_class)) {
+ dst->ThrowArrayStoreException(object);
+ return;
+ }
dst->SetFieldObject(dst_offset, object, false);
src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*));
dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*));
@@ -2567,9 +2582,10 @@
// Check class is loaded or this is java.lang.String that has a
// circularity issue during loading the names of its members
DCHECK(IsLoaded() || IsErroneous() ||
- this == String::GetJavaLangString() ||
- this == Field::GetJavaLangReflectField() ||
- this == Method::GetJavaLangReflectMethod()) << PrettyClass(this);
+ this == String::GetJavaLangString() ||
+ this == Field::GetJavaLangReflectField() ||
+ this == Method::GetConstructorClass() ||
+ this == Method::GetMethodClass()) << PrettyClass(this);
return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
}
diff --git a/src/thread.cc b/src/thread.cc
index 8005072..71b9090 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -484,8 +484,9 @@
DCHECK_LT(frame_size, 1024u);
byte* next_sp = reinterpret_cast<byte*>(sp_) + frame_size;
sp_ = reinterpret_cast<Method**>(next_sp);
- if(*sp_ != NULL) {
- DCHECK_EQ((*sp_)->GetClass(), Method::GetMethodClass());
+ if (*sp_ != NULL) {
+ DCHECK((*sp_)->GetClass() == Method::GetMethodClass() ||
+ (*sp_)->GetClass() == Method::GetConstructorClass());
}
}