summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2012-01-10 17:35:46 -0800
committerIan Rogers <irogers@google.com>2012-01-10 17:35:46 -0800
commitcab0101c2b28a6be003f177ccb04347f0a6b62d7 (patch)
tree5620c2074caa44458aaebceccd5229557174d3fb
parent672297c77a92e31e88feb179e4548284ba17d330 (diff)
downloadart-cab0101c2b28a6be003f177ccb04347f0a6b62d7.zip
art-cab0101c2b28a6be003f177ccb04347f0a6b62d7.tar.gz
art-cab0101c2b28a6be003f177ccb04347f0a6b62d7.tar.bz2
Fix 086-null-super and 087-gc-after-link
Parallel run-test means that the dex files for 086 and 087 are no longer always in test.jar. Correct the behavior of the class linker when Classloader.loadClass returns null to be the behavior of Dalvik. Change-Id: Icf6363e118d03a01060012ac558b5f1a484d74f9
-rw-r--r--src/class_linker.cc23
-rw-r--r--src/dalvik_system_DexFile.cc19
-rw-r--r--test/086-null-super/src/Main.java2
-rw-r--r--test/087-gc-after-link/src/Main.java2
4 files changed, 39 insertions, 7 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 1355cbf..b06d108 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -91,6 +91,14 @@ void ThrowNoSuchFieldError(const StringPiece& scope, Class* c, const StringPiece
Thread::Current()->ThrowNewException("Ljava/lang/NoSuchFieldError;", msg.str().c_str());
}
+void ThrowNullPointerException(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
+void ThrowNullPointerException(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ Thread::Current()->ThrowNewExceptionV("Ljava/lang/NullPointerException;", fmt, args);
+ va_end(args);
+}
+
void ThrowEarlierClassFailure(Class* c) {
/*
* The class failed to initialize on a previous attempt, so we want to throw
@@ -1152,7 +1160,13 @@ Class* ClassLinker::FindClass(const char* descriptor, const ClassLoader* class_l
}
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()));
- if (!env->ExceptionOccurred()) {
+ if (result.get() == NULL) {
+ // broken loader - throw NPE to be compatible with Dalvik
+ ThrowNullPointerException("ClassLoader.loadClass returned null for %s",
+ class_name_string.c_str());
+ return NULL;
+ } else if (!env->ExceptionOccurred()) {
+ // success, return Class*
return Decode<Class*>(env, result.get());
} else {
env->ExceptionClear(); // Failed to find class fall-through to NCDFE
@@ -2299,9 +2313,7 @@ bool ClassLinker::LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& d
CHECK_EQ(Class::kStatusIdx, klass->GetStatus());
StringPiece descriptor(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
const DexFile::ClassDef* class_def = dex_file.FindClassDef(descriptor);
- if (class_def == NULL) {
- return false;
- }
+ CHECK(class_def != NULL);
uint16_t super_class_idx = class_def->superclass_idx_;
if (super_class_idx != DexFile::kDexNoIndex16) {
Class* super_class = ResolveType(dex_file, super_class_idx, klass.get());
@@ -2901,7 +2913,8 @@ Class* ClassLinker::ResolveType(const DexFile& dex_file,
// same name to be loaded simultaneously by different loaders
dex_cache->SetResolvedType(type_idx, resolved);
} else {
- DCHECK(Thread::Current()->IsExceptionPending());
+ CHECK(Thread::Current()->IsExceptionPending())
+ << "Expected pending exception for failed resolution of: " << descriptor;
}
}
return resolved;
diff --git a/src/dalvik_system_DexFile.cc b/src/dalvik_system_DexFile.cc
index 7fce25f..7680e0f 100644
--- a/src/dalvik_system_DexFile.cc
+++ b/src/dalvik_system_DexFile.cc
@@ -176,7 +176,26 @@ jclass DexFile_defineClass(JNIEnv* env, jclass, jstring javaName, jobject javaLo
class_linker->RegisterDexFile(*dex_file);
Class* result = class_linker->DefineClass(descriptor, class_loader, *dex_file, *dex_class_def);
if (env->ExceptionCheck()) {
+ // Remember exception and clear it
+ jthrowable exception = env->ExceptionOccurred();
env->ExceptionClear();
+ // If we threw a "class not found" exception, stifle it, since the contract in the higher
+ // method says we simply return null if the class is not found.
+ static const char* ignored_exception_classes[2] = {
+ "java/lang/ClassNotFoundException",
+ "java/lang/NoClassDefFoundError"
+ };
+ bool clear_exception = false;
+ for (int i = 0; i < 2; i++) {
+ jclass exception_class = env->FindClass(ignored_exception_classes[i]);
+ if (env->IsInstanceOf(exception, exception_class)) {
+ clear_exception = true;
+ break;
+ }
+ }
+ if (!clear_exception) {
+ env->Throw(exception);
+ }
return NULL;
}
return AddLocalReference<jclass>(env, result);
diff --git a/test/086-null-super/src/Main.java b/test/086-null-super/src/Main.java
index 6decb20..0b8b2f5 100644
--- a/test/086-null-super/src/Main.java
+++ b/test/086-null-super/src/Main.java
@@ -55,7 +55,7 @@ public class Main {
private static final String CLASS_NAME =
"Main$BrokenDexLoader$Inaccessible";
- private static final String DEX_FILE = "test.jar";
+ private static final String DEX_FILE = "/data/art-test/086-null-super.jar";
public BrokenDexLoader(ClassLoader parent) {
super(parent);
diff --git a/test/087-gc-after-link/src/Main.java b/test/087-gc-after-link/src/Main.java
index dc68f9f..12fa56a 100644
--- a/test/087-gc-after-link/src/Main.java
+++ b/test/087-gc-after-link/src/Main.java
@@ -55,7 +55,7 @@ public class Main {
private static final String CLASS_NAME =
"Main$BrokenDexLoader$Inaccessible";
- private static final String DEX_FILE = "test.jar";
+ private static final String DEX_FILE = "/data/art-test/087-gc-after-link.jar";
public BrokenDexLoader(ClassLoader parent) {
super(parent);