class JitCompileTask : public Task {
public:
- explicit JitCompileTask(ArtMethod* method) : method_(method) {}
+ explicit JitCompileTask(ArtMethod* method) : method_(method) {
+ ScopedObjectAccess soa(Thread::Current());
+ // Add a global ref to the class to prevent class unloading until compilation is done.
+ klass_ = soa.Vm()->AddGlobalRef(soa.Self(), method_->GetDeclaringClass());
+ CHECK(klass_ != nullptr);
+ }
+
+ ~JitCompileTask() {
+ ScopedObjectAccess soa(Thread::Current());
+ soa.Vm()->DeleteGlobalRef(soa.Self(), klass_);
+ }
virtual void Run(Thread* self) OVERRIDE {
ScopedObjectAccess soa(self);
private:
ArtMethod* const method_;
+ jobject klass_;
DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask);
};
}
}
+class WaitForCompilationToFinishTask : public Task {
+ public:
+ WaitForCompilationToFinishTask() : barrier_(0) {}
+
+ void Wait(Thread* self) {
+ barrier_.Increment(self, 1);
+ }
+
+ virtual void Run(Thread* self) OVERRIDE {
+ barrier_.Pass(self);
+ }
+
+ private:
+ Barrier barrier_;
+ DISALLOW_COPY_AND_ASSIGN(WaitForCompilationToFinishTask);
+};
+
+void JitInstrumentationCache::WaitForCompilationToFinish(Thread* self) {
+ std::unique_ptr<WaitForCompilationToFinishTask> task(new WaitForCompilationToFinishTask);
+ thread_pool_->AddTask(self, task.get());
+ task->Wait(self);
+}
+
} // namespace jit
} // namespace art
Constructor constructor =
pathClassLoader.getDeclaredConstructor(String.class, ClassLoader.class);
try {
- testUnloadClassAndLoader(constructor);
+ testUnloadClass(constructor);
+ testUnloadLoader(constructor);
// Test that we don't unload if we have a Method keeping the class live.
testNoUnloadInvoke(constructor);
// Test that we don't unload if we have an instance.
private static void stressTest(Constructor constructor) throws Exception {
for (int i = 0; i <= 100; ++i) {
- setUpUnloadLoader(constructor);
+ setUpUnloadLoader(constructor, false);
if (i % 10 == 0) {
Runtime.getRuntime().gc();
}
}
}
- private static void testUnloadClassAndLoader(Constructor constructor) throws Exception {
- WeakReference<ClassLoader> loader = setUpUnloadLoader(constructor);
+ private static void testUnloadClass(Constructor constructor) throws Exception {
WeakReference<Class> klass = setUpUnloadClass(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(klass.get());
System.out.println(klass2.get());
- System.out.println(loader.get());
+ }
+
+ private static void testUnloadLoader(Constructor constructor)
+ throws Exception {
+ WeakReference<ClassLoader> loader = setUpUnloadLoader(constructor, true);
+ // 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 testLoadAndUnloadLibrary(Constructor constructor) throws Exception {
System.out.println("loader null " + isNull);
}
- private static WeakReference<Class> setUpUnloadClass(Constructor constructor)
- throws Exception {
+ private static WeakReference<Class> setUpUnloadClass(Constructor constructor) throws Exception {
ClassLoader loader = (ClassLoader) constructor.newInstance(
DEX_FILE, ClassLoader.getSystemClassLoader());
Class intHolder = loader.loadClass("IntHolder");
System.out.println((int) getValue.invoke(intHolder));
setValue.invoke(intHolder, 2);
System.out.println((int) getValue.invoke(intHolder));
+ waitForCompilation(intHolder);
return new WeakReference(intHolder);
}
- private static WeakReference<ClassLoader> setUpUnloadLoader(Constructor constructor)
+ private static WeakReference<ClassLoader> setUpUnloadLoader(Constructor constructor,
+ boolean waitForCompilation)
throws Exception {
ClassLoader loader = (ClassLoader) constructor.newInstance(
DEX_FILE, ClassLoader.getSystemClassLoader());
Class intHolder = loader.loadClass("IntHolder");
Method setValue = intHolder.getDeclaredMethod("setValue", Integer.TYPE);
setValue.invoke(intHolder, 2);
+ if (waitForCompilation) {
+ waitForCompilation(intHolder);
+ }
return new WeakReference(loader);
}
+ private static void waitForCompilation(Class intHolder) throws Exception {
+ // Load the native library so that we can call waitForCompilation.
+ Method loadLibrary = intHolder.getDeclaredMethod("loadLibrary", String.class);
+ loadLibrary.invoke(intHolder, nativeLibraryName);
+ // Wait for JIT compilation to finish since the async threads may prevent unloading.
+ Method waitForCompilation = intHolder.getDeclaredMethod("waitForCompilation");
+ waitForCompilation.invoke(intHolder);
+ }
+
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);
+ Method loadLibrary = intHolder.getDeclaredMethod("loadLibrary", String.class);
+ loadLibrary.invoke(intHolder, nativeLibraryName);
return new WeakReference(loader);
}
}