Initialize classes in GetFieldID/GetMethodID.
Change-Id: I2ccf5d021067e4d18803bd505d5bdc1fcbbb3433
diff --git a/src/class_linker.cc b/src/class_linker.cc
index a7d10f4..448a542 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -884,7 +884,6 @@
Method* clinit = klass->FindDeclaredDirectMethod("<clinit>", "()V");
if (clinit != NULL) {
- } else {
// JValue unused;
// TODO: dvmCallMethod(self, method, NULL, &unused);
// UNIMPLEMENTED(FATAL);
@@ -913,7 +912,7 @@
klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
const Class* super = klass->GetSuperClass();
for (int i = super->NumVirtualMethods() - 1; i >= 0; --i) {
- const Method* method = klass->GetVirtualMethod(i);
+ const Method* method = super->GetVirtualMethod(i);
if (method != super->GetVirtualMethod(i) &&
!HasSameMethodDescriptorClasses(method, super, klass)) {
LG << "Classes resolve differently in superclass";
@@ -995,7 +994,6 @@
bool ClassLinker::InitializeSuperClass(Class* klass) {
CHECK(klass != NULL);
- MutexLock mu(classes_lock_);
if (!klass->IsInterface() && klass->HasSuperClass()) {
Class* super_class = klass->GetSuperClass();
if (super_class->GetStatus() != Class::kStatusInitialized) {
@@ -1014,6 +1012,18 @@
return true;
}
+bool ClassLinker::EnsureInitialized(Class* c) {
+ CHECK(c != NULL);
+ if (c->IsInitialized()) {
+ return true;
+ }
+
+ c->MonitorExit();
+ InitializeClass(c);
+ c->MonitorEnter();
+ return !Thread::Current()->IsExceptionPending();
+}
+
void ClassLinker::InitializeStaticFields(Class* klass) {
size_t num_static_fields = klass->NumStaticFields();
if (num_static_fields == 0) {
@@ -1028,6 +1038,10 @@
const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
CHECK(dex_class_def != NULL);
const byte* addr = dex_file.GetEncodedArray(*dex_class_def);
+ if (addr == NULL) {
+ // All this class' static fields have default values.
+ return;
+ }
size_t array_size = DecodeUnsignedLeb128(&addr);
for (size_t i = 0; i < array_size; ++i) {
Field* field = klass->GetStaticField(i);
diff --git a/src/class_linker.h b/src/class_linker.h
index 90ac678..e83c850 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -39,7 +39,8 @@
return FindClass(descriptor, NULL);
}
- bool InitializeClass(Class* klass);
+ // Returns true on success, false if there's an exception pending.
+ bool EnsureInitialized(Class* c);
void RegisterDexFile(const DexFile* dex_file);
@@ -53,6 +54,8 @@
void Init(const std::vector<DexFile*>& boot_class_path_);
+ bool InitializeClass(Class* klass);
+
// For early bootstrapping by Init
Class* AllocClass(Class* java_lang_Class);
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 733a307..8e8ecd3 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -454,8 +454,8 @@
jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
Class* c = Decode<Class*>(ts, jni_class);
- if (!c->IsInitialized()) {
- // TODO: initialize the class
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
+ return NULL;
}
Method* method = NULL;
@@ -492,8 +492,8 @@
jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
Class* c = Decode<Class*>(ts, jni_class);
- if (!c->IsInitialized()) {
- // TODO: initialize the class
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
+ return NULL;
}
Field* field = NULL;
diff --git a/src/thread.cc b/src/thread.cc
index 1cb037e..44f0946 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -46,7 +46,7 @@
CHECK(GetOwner() == Thread::Current());
int result = pthread_mutex_unlock(&lock_impl_);
CHECK_EQ(result, 0);
- SetOwner(Thread::Current());
+ SetOwner(NULL);
}
void* ThreadStart(void *arg) {