summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-11-19 14:05:21 -0800
committerIan Rogers <irogers@google.com>2014-11-19 14:05:21 -0800
commit3242729362b74d22f11d8bc7b4800ba0a8695df6 (patch)
treee3ac6dbb1d4f1f6295ed4a856473c6f92c88be22 /runtime
parent834896de1c955c04d781d2bf8c53573f94ce8c3e (diff)
downloadart-3242729362b74d22f11d8bc7b4800ba0a8695df6.tar.gz
art-3242729362b74d22f11d8bc7b4800ba0a8695df6.tar.bz2
art-3242729362b74d22f11d8bc7b4800ba0a8695df6.zip
Avoid JNI call with pending OOME.
If EnsureResolved fails with an exception then FindClassInPathClassLoader may fall-through to a call to NewStringUTF with a pending exception. Bug: 15446488 Change-Id: I007f7bee7c50aa588d0b1c776da67a38314dc897
Diffstat (limited to 'runtime')
-rw-r--r--runtime/class_linker.cc24
-rw-r--r--runtime/class_linker.h4
2 files changed, 17 insertions, 11 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 68e20f2763..e1b79c9f87 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2060,6 +2060,7 @@ mirror::Class* ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlready
Thread* self, const char* descriptor,
size_t hash,
Handle<mirror::ClassLoader> class_loader) {
+ // Can we special case for a well understood PathClassLoader with the BootClassLoader as parent?
if (class_loader->GetClass() !=
soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader) ||
class_loader->GetParent()->GetClass() !=
@@ -2071,17 +2072,21 @@ mirror::Class* ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlready
if (pair.second != nullptr) {
mirror::Class* klass = LookupClass(self, descriptor, hash, nullptr);
if (klass != nullptr) {
- return EnsureResolved(self, descriptor, klass);
+ // May return null if resolution on another thread fails.
+ klass = EnsureResolved(self, descriptor, klass);
+ } else {
+ // May OOME.
+ klass = DefineClass(self, descriptor, hash, NullHandle<mirror::ClassLoader>(), *pair.first,
+ *pair.second);
}
- klass = DefineClass(self, descriptor, hash, NullHandle<mirror::ClassLoader>(), *pair.first,
- *pair.second);
- if (klass != nullptr) {
- return klass;
+ if (klass == nullptr) {
+ CHECK(self->IsExceptionPending()) << descriptor;
+ self->ClearException();
}
- CHECK(self->IsExceptionPending()) << descriptor;
- self->ClearException();
+ return klass;
} else {
- // RegisterDexFile may allocate dex caches (and cause thread suspension).
+ // Handle as if this is the child PathClassLoader.
+ // Handles as RegisterDexFile may allocate dex caches (and cause thread suspension).
StackHandleScope<3> hs(self);
// The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
// We need to get the DexPathList and loop through it.
@@ -2138,8 +2143,9 @@ mirror::Class* ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlready
}
}
}
+ self->AssertNoPendingException();
+ return nullptr;
}
- return nullptr;
}
mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor,
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 006354f948..b78d0b5bc3 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -117,8 +117,8 @@ class ClassLinker {
Handle<mirror::ClassLoader> class_loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Find a class in the path class loader, loading it if necessary. Hash function is supposed to
- // be ComputeModifiedUtf8Hash(descriptor).
+ // Find a class in the path class loader, loading it if necessary without using JNI. Hash
+ // function is supposed to be ComputeModifiedUtf8Hash(descriptor).
mirror::Class* FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
Thread* self, const char* descriptor, size_t hash,
Handle<mirror::ClassLoader> class_loader)