Pre-allocate the NoClassDefFoundError to be thrown for boot classes.
Bring over a Dalvik "optimization".
Bug: 12804658
Bug: 16853450
Change-Id: I6419de7bd2ba18d91479cb52489104954f5c4524
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 7ba0d92..0746e0c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2015,10 +2015,18 @@
if (descriptor[0] == '[') {
return CreateArrayClass(self, descriptor, class_loader);
} else if (class_loader.Get() == nullptr) {
+ // The boot class loader, search the boot class path.
ClassPathEntry pair = FindInClassPath(descriptor, boot_class_path_);
if (pair.second != nullptr) {
StackHandleScope<1> hs(self);
return DefineClass(descriptor, NullHandle<mirror::ClassLoader>(), *pair.first, *pair.second);
+ } else {
+ // The boot class loader is searched ahead of the application class loader, failures are
+ // expected and will be wrapped in a ClassNotFoundException. Use the pre-allocated error to
+ // trigger the chaining with a proper stack trace.
+ mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError();
+ self->SetException(ThrowLocation(), pre_allocated);
+ return nullptr;
}
} else if (Runtime::Current()->UseCompileTimeClassPath()) {
// First try with the bootstrap class loader.
@@ -2028,7 +2036,8 @@
return EnsureResolved(self, descriptor, klass);
}
}
- // If the lookup failed search the boot class path. We don't perform a recursive call to avoid a NoClassDefFoundError being allocated.
+ // If the lookup failed search the boot class path. We don't perform a recursive call to avoid
+ // a NoClassDefFoundError being allocated.
ClassPathEntry pair = FindInClassPath(descriptor, boot_class_path_);
if (pair.second != nullptr) {
StackHandleScope<1> hs(self);
@@ -2057,6 +2066,7 @@
ScopedLocalRef<jobject> class_name_object(soa.Env(),
soa.Env()->NewStringUTF(class_name_string.c_str()));
if (class_name_object.get() == nullptr) {
+ DCHECK(self->IsExceptionPending()); // OOME.
return nullptr;
}
CHECK(class_loader_object.get() != nullptr);
@@ -2070,7 +2080,7 @@
} else if (result.get() == nullptr) {
// broken loader - throw NPE to be compatible with Dalvik
ThrowNullPointerException(nullptr, StringPrintf("ClassLoader.loadClass returned null for %s",
- class_name_string.c_str()).c_str());
+ class_name_string.c_str()).c_str());
return nullptr;
} else {
// success, return mirror::Class*