Call JNI_OnUnload when class loaders get collected
Added test case to 141-class-unload.
Bug: 22720414
Change-Id: I0575fae72521520a17587e8b0088bf8112705ad8
diff --git a/test/141-class-unload/expected.txt b/test/141-class-unload/expected.txt
index be2671e..124398f 100644
--- a/test/141-class-unload/expected.txt
+++ b/test/141-class-unload/expected.txt
@@ -7,3 +7,6 @@
null
loader null false
loader null false
+JNI_OnLoad called
+JNI_OnUnload called
+null
diff --git a/test/141-class-unload/jni_unload.cc b/test/141-class-unload/jni_unload.cc
new file mode 100644
index 0000000..894f28c
--- /dev/null
+++ b/test/141-class-unload/jni_unload.cc
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+
+#include <iostream>
+
+extern "C" JNIEXPORT void JNI_OnUnload(JavaVM*, void *) {
+ // std::cout since LOG(INFO) adds extra stuff like pid.
+ std::cout << "JNI_OnUnload called" << std::endl;
+}
diff --git a/test/141-class-unload/src-ex/IntHolder.java b/test/141-class-unload/src-ex/IntHolder.java
index 0a1c1e6..b4651af 100644
--- a/test/141-class-unload/src-ex/IntHolder.java
+++ b/test/141-class-unload/src-ex/IntHolder.java
@@ -30,4 +30,8 @@
public static void runGC() {
Runtime.getRuntime().gc();
}
+
+ public static void loadLibrary(String name) {
+ System.loadLibrary(name);
+ }
}
diff --git a/test/141-class-unload/src/Main.java b/test/141-class-unload/src/Main.java
index 3a2ac9b..da15746 100644
--- a/test/141-class-unload/src/Main.java
+++ b/test/141-class-unload/src/Main.java
@@ -20,8 +20,10 @@
public class Main {
static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/141-class-unload-ex.jar";
+ static String nativeLibraryName;
public static void main(String[] args) throws Exception {
+ nativeLibraryName = args[0];
Class pathClassLoader = Class.forName("dalvik.system.PathClassLoader");
if (pathClassLoader == null) {
throw new AssertionError("Couldn't find path class loader class");
@@ -34,6 +36,8 @@
testNoUnloadInvoke(constructor);
// Test that we don't unload if we have an instance.
testNoUnloadInstance(constructor);
+ // Test JNI_OnLoad and JNI_OnUnload.
+ testLoadAndUnloadLibrary(constructor);
// Stress test to make sure we dont leak memory.
stressTest(constructor);
} catch (Exception e) {
@@ -63,6 +67,14 @@
System.out.println(loader.get());
}
+ private static void testLoadAndUnloadLibrary(Constructor constructor) throws Exception {
+ WeakReference<ClassLoader> loader = setUpLoadLibrary(constructor);
+ // No strong refernces to class loader, should get unloaded.
+ Runtime.getRuntime().gc();
+ // If the weak reference is cleared, then it was unloaded.
+ System.out.println(loader.get());
+ }
+
private static void testNoUnloadInvoke(Constructor constructor) throws Exception {
WeakReference<ClassLoader> loader =
new WeakReference((ClassLoader) constructor.newInstance(
@@ -109,4 +121,13 @@
return new WeakReference(loader);
}
+ private static WeakReference<ClassLoader> setUpLoadLibrary(Constructor constructor)
+ throws Exception {
+ ClassLoader loader = (ClassLoader) constructor.newInstance(
+ DEX_FILE, ClassLoader.getSystemClassLoader());
+ Class intHolder = loader.loadClass("IntHolder");
+ Method setValue = intHolder.getDeclaredMethod("loadLibrary", String.class);
+ setValue.invoke(intHolder, nativeLibraryName);
+ return new WeakReference(loader);
+ }
}