summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2016-04-12 16:54:48 -0700
committer Mathieu Chartier <mathieuc@google.com> 2016-04-12 17:59:44 -0700
commit6d25cf6cbda1b95fb014a3fd22c01a6bdf47725e (patch)
treed718c92777b01053a47c14a891a6d8dd493d0821
parent780b46126af0b4239ff5a3a88f347548d960bbe4 (diff)
Fix InsertDexFileInToClassLoader to handle null class loaders
Maybe used by legacy apps. This functionality is planned for deprecation. Bug: 27954959 (cherry picked from commit f2bf9d640e37b72be8b4f6016d4aa95a0e27b7b4) Change-Id: I1ae2cf1e33f2f1b237a41c8cc50d2a814a52a95a
-rw-r--r--runtime/class_linker.cc5
-rw-r--r--runtime/class_linker.h1
-rw-r--r--test/068-classloader/expected.txt1
-rw-r--r--test/068-classloader/src/Main.java25
4 files changed, 29 insertions, 3 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 18def2df2e..1e7ee65eac 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7760,12 +7760,11 @@ void ClassLinker::VisitClassLoaders(ClassLoaderVisitor* visitor) const {
void ClassLinker::InsertDexFileInToClassLoader(mirror::Object* dex_file,
mirror::ClassLoader* class_loader) {
DCHECK(dex_file != nullptr);
- DCHECK(class_loader != nullptr);
Thread* const self = Thread::Current();
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
- ClassTable* const table = class_loader->GetClassTable();
+ ClassTable* const table = ClassTableForClassLoader(class_loader);
DCHECK(table != nullptr);
- if (table->InsertDexFile(dex_file)) {
+ if (table->InsertDexFile(dex_file) && class_loader != nullptr) {
// It was not already inserted, perform the write barrier to let the GC know the class loader's
// class table was modified.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index b4b7f34967..5de502b540 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -595,6 +595,7 @@ class ClassLinker {
REQUIRES(!Locks::classlinker_classes_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
+ // May be called with null class_loader due to legacy code. b/27954959
void InsertDexFileInToClassLoader(mirror::Object* dex_file, mirror::ClassLoader* class_loader)
REQUIRES(!Locks::classlinker_classes_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/test/068-classloader/expected.txt b/test/068-classloader/expected.txt
index 8725799fe1..ae937e04fb 100644
--- a/test/068-classloader/expected.txt
+++ b/test/068-classloader/expected.txt
@@ -13,3 +13,4 @@ Got LinkageError on DI (early)
Got LinkageError on IDI (early)
class Main
Got expected ClassNotFoundException
+Loaded class into null class loader
diff --git a/test/068-classloader/src/Main.java b/test/068-classloader/src/Main.java
index 361e2938e3..b2d843b351 100644
--- a/test/068-classloader/src/Main.java
+++ b/test/068-classloader/src/Main.java
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
/**
* Class loader test.
*/
@@ -62,6 +65,28 @@ public class Main {
testSeparation();
testClassForName();
+
+ testNullClassLoader();
+ }
+
+ static void testNullClassLoader() {
+ try {
+ /* this is the "alternate" DEX/Jar file */
+ String DEX_FILE = System.getenv("DEX_LOCATION") + "/068-classloader-ex.jar";
+ /* on Dalvik, this is a DexFile; otherwise, it's null */
+ Class mDexClass = Class.forName("dalvik.system.DexFile");
+ Constructor ctor = mDexClass.getConstructor(new Class[] {String.class});
+ Object mDexFile = ctor.newInstance(DEX_FILE);
+ Method meth = mDexClass.getMethod("loadClass",
+ new Class[] { String.class, ClassLoader.class });
+ Object klass = meth.invoke(mDexFile, "Mutator", null);
+ if (klass == null) {
+ throw new AssertionError("loadClass with nullclass loader failed");
+ }
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ System.out.println("Loaded class into null class loader");
}
static void testSeparation() {