Make 141-class-unload more robust under JIT.
Make sure jit is stopped before counting maps.
bug: 29712509
test: 141-class-unload
Change-Id: I52c0fed74556fa228cd73c9c0bc6a1d019df0a1c
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index dac2e60..b7125a8 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -291,7 +291,7 @@
// is not null when we instrument.
thread_pool_.reset(new ThreadPool("Jit thread pool", 1));
thread_pool_->SetPthreadPriority(kJitPoolThreadPthreadPriority);
- thread_pool_->StartWorkers(Thread::Current());
+ Start();
}
void Jit::DeleteThreadPool() {
@@ -710,14 +710,23 @@
}
}
+void Jit::Stop() {
+ Thread* self = Thread::Current();
+ // TODO(ngeoffray): change API to not require calling WaitForCompilationToFinish twice.
+ WaitForCompilationToFinish(self);
+ GetThreadPool()->StopWorkers(self);
+ WaitForCompilationToFinish(self);
+}
+
+void Jit::Start() {
+ GetThreadPool()->StartWorkers(Thread::Current());
+}
+
ScopedJitSuspend::ScopedJitSuspend() {
jit::Jit* jit = Runtime::Current()->GetJit();
was_on_ = (jit != nullptr) && (jit->GetThreadPool() != nullptr);
if (was_on_) {
- Thread* self = Thread::Current();
- jit->WaitForCompilationToFinish(self);
- jit->GetThreadPool()->StopWorkers(self);
- jit->WaitForCompilationToFinish(self);
+ jit->Stop();
}
}
@@ -725,7 +734,7 @@
if (was_on_) {
DCHECK(Runtime::Current()->GetJit() != nullptr);
DCHECK(Runtime::Current()->GetJit()->GetThreadPool() != nullptr);
- Runtime::Current()->GetJit()->GetThreadPool()->StartWorkers(Thread::Current());
+ Runtime::Current()->GetJit()->Start();
}
}
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index a230c78..05c3905 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -179,6 +179,12 @@
return thread_pool_.get();
}
+ // Stop the JIT by waiting for all current compilations and enqueued compilations to finish.
+ void Stop();
+
+ // Start JIT threads.
+ void Start();
+
private:
Jit();
diff --git a/test/141-class-unload/expected.txt b/test/141-class-unload/expected.txt
index 0a03ecb..a1c5fa8 100644
--- a/test/141-class-unload/expected.txt
+++ b/test/141-class-unload/expected.txt
@@ -20,5 +20,6 @@
JNI_OnLoad called
class null false test
JNI_OnUnload called
+JNI_OnLoad called
Number of loaded unload-ex maps 0
Too small false
diff --git a/test/141-class-unload/jni_unload.cc b/test/141-class-unload/jni_unload.cc
index bbbb0a6..9b7e171 100644
--- a/test/141-class-unload/jni_unload.cc
+++ b/test/141-class-unload/jni_unload.cc
@@ -32,5 +32,19 @@
}
}
+extern "C" JNIEXPORT void JNICALL Java_Main_stopJit(JNIEnv*, jclass) {
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ if (jit != nullptr) {
+ jit->Stop();
+ }
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_startJit(JNIEnv*, jclass) {
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ if (jit != nullptr) {
+ jit->Start();
+ }
+}
+
} // namespace
} // namespace art
diff --git a/test/141-class-unload/src/Main.java b/test/141-class-unload/src/Main.java
index 2a6e944..595c70d 100644
--- a/test/141-class-unload/src/Main.java
+++ b/test/141-class-unload/src/Main.java
@@ -55,11 +55,15 @@
}
private static void testOatFilesUnloaded(int pid) throws Exception {
+ System.loadLibrary(nativeLibraryName);
+ // Stop the JIT to ensure its threads and work queue are not keeping classes
+ // artifically alive.
+ stopJit();
+ Runtime.getRuntime().gc();
+ System.runFinalization();
BufferedReader reader = new BufferedReader(new FileReader ("/proc/" + pid + "/maps"));
String line;
int count = 0;
- Runtime.getRuntime().gc();
- System.runFinalization();
while ((line = reader.readLine()) != null) {
if (line.contains("@141-class-unload-ex.jar")) {
System.out.println(line);
@@ -67,6 +71,7 @@
}
}
System.out.println("Number of loaded unload-ex maps " + count);
+ startJit();
}
private static void stressTest(Constructor<?> constructor) throws Exception {
@@ -229,4 +234,7 @@
private static int getPid() throws Exception {
return Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
}
+
+ public static native void stopJit();
+ public static native void startJit();
}