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) {