Merge "Make methods and fields accessible by default in art." into dalvik-dev
diff --git a/src/class_linker.cc b/src/class_linker.cc
index c214b5f..4598ae9 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -979,42 +979,50 @@
   // Class is not yet loaded.
   if (descriptor[0] == '[') {
     return CreateArrayClass(descriptor, class_loader);
-  }
-  if (class_loader == NULL) {
-    DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_);
-    if (pair.second == NULL) {
-      std::string name(PrintableString(descriptor));
-      ThrowNoClassDefFoundError("Class %s not found in boot class loader", name.c_str());
-      return NULL;
-    }
-    return DefineClass(descriptor, NULL, *pair.first, *pair.second);
-  }
 
-  if (ClassLoader::UseCompileTimeClassPath()) {
+  } else if (class_loader == NULL) {
+    DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_);
+    if (pair.second != NULL) {
+      return DefineClass(descriptor, NULL, *pair.first, *pair.second);
+    }
+
+  } else if (ClassLoader::UseCompileTimeClassPath()) {
+    // first try the boot class path
+    Class* system_class = FindSystemClass(descriptor);
+    if (system_class != NULL) {
+      return system_class;
+    }
+    CHECK(self->IsExceptionPending());
+    self->ClearException();
+
+    // next try the compile time class path
     const std::vector<const DexFile*>& class_path
         = ClassLoader::GetCompileTimeClassPath(class_loader);
     DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, class_path);
-    if (pair.second == NULL) {
-      return FindSystemClass(descriptor);
+    if (pair.second != NULL) {
+      return DefineClass(descriptor, class_loader, *pair.first, *pair.second);
     }
-    return DefineClass(descriptor, class_loader, *pair.first, *pair.second);
+
+  } else {
+    std::string class_name_string = DescriptorToDot(descriptor);
+    ScopedThreadStateChange(self, Thread::kNative);
+    JNIEnv* env = self->GetJniEnv();
+    ScopedLocalRef<jclass> c(env, AddLocalReference<jclass>(env, GetClassRoot(kJavaLangClassLoader)));
+    CHECK(c.get() != NULL);
+    // TODO: cache method?
+    jmethodID mid = env->GetMethodID(c.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
+    CHECK(mid != NULL);
+    ScopedLocalRef<jobject> class_name_object(env, env->NewStringUTF(class_name_string.c_str()));
+    if (class_name_object.get() == NULL) {
+      return NULL;
+    }
+    ScopedLocalRef<jobject> class_loader_object(env, AddLocalReference<jobject>(env, class_loader));
+    ScopedLocalRef<jobject> result(env, env->CallObjectMethod(class_loader_object.get(), mid, class_name_object.get()));
+    return Decode<Class*>(env, result.get());
   }
 
-  std::string class_name_string = DescriptorToDot(descriptor);
-  ScopedThreadStateChange(self, Thread::kNative);
-  JNIEnv* env = self->GetJniEnv();
-  ScopedLocalRef<jclass> c(env, AddLocalReference<jclass>(env, GetClassRoot(kJavaLangClassLoader)));
-  CHECK(c.get() != NULL);
-  // TODO: cache method?
-  jmethodID mid = env->GetMethodID(c.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
-  CHECK(mid != NULL);
-  ScopedLocalRef<jobject> class_name_object(env, env->NewStringUTF(class_name_string.c_str()));
-  if (class_name_object.get() == NULL) {
-    return NULL;
-  }
-  ScopedLocalRef<jobject> class_loader_object(env, AddLocalReference<jobject>(env, class_loader));
-  ScopedLocalRef<jobject> result(env, env->CallObjectMethod(class_loader_object.get(), mid, class_name_object.get()));
-  return Decode<Class*>(env, result.get());
+  ThrowNoClassDefFoundError("Class %s not found", PrintableString(descriptor).c_str());
+  return NULL;
 }
 
 Class* ClassLinker::DefineClass(const std::string& descriptor,
@@ -2707,7 +2715,8 @@
   if (resolved != NULL) {
     dex_cache->SetResolvedField(field_idx, resolved);
   } else {
-    DCHECK(Thread::Current()->IsExceptionPending())
+    // TODO: this check fails when the app class path contains a class from the boot class path
+    CHECK(Thread::Current()->IsExceptionPending())
         << PrettyClass(klass) << " " << name << " " << type << " " << is_static;
   }
   return resolved;
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index f4376ec..0ed6cea 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -116,12 +116,18 @@
   std::vector<Field*> fields;
   for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
     Field* f = c->GetInstanceField(i);
+    if (env->ExceptionOccurred()) {
+      return NULL;
+    }
     if (IsVisibleField(f, publicOnly)) {
       fields.push_back(f);
     }
   }
   for (size_t i = 0; i < c->NumStaticFields(); ++i) {
     Field* f = c->GetStaticField(i);
+    if (env->ExceptionOccurred()) {
+      return NULL;
+    }
     if (IsVisibleField(f, publicOnly)) {
       fields.push_back(f);
     }
@@ -147,12 +153,18 @@
   std::vector<Method*> methods;
   for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
     Method* m = c->GetVirtualMethod(i);
+    if (env->ExceptionOccurred()) {
+      return NULL;
+    }
     if (IsVisibleMethod(m, publicOnly)) {
       methods.push_back(m);
     }
   }
   for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
     Method* m = c->GetDirectMethod(i);
+    if (env->ExceptionOccurred()) {
+      return NULL;
+    }
     if (IsVisibleMethod(m, publicOnly)) {
       methods.push_back(m);
     }