--- old/test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java 2018-05-02 11:26:03.070069810 -0700 +++ new/test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java 2018-05-02 11:26:02.750069826 -0700 @@ -31,17 +31,49 @@ */ import java.io.IOException; +import java.lang.ref.WeakReference; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; public class NativeLibraryTest { static final Path CLASSES = Paths.get("classes"); static int unloadedCount = 0; + /** No guarantees, but effective in practice. */ + static void forceFullGc() { + CountDownLatch finalizeDone = new CountDownLatch(1); + WeakReference ref = new WeakReference(new Object() { + protected void finalize() { finalizeDone.countDown(); }}); + try { + for (int i = 0; i < 10; i++) { + System.gc(); + if (finalizeDone.await(1L, TimeUnit.SECONDS) && ref.get() == null) { + System.runFinalization(); // try to pick up stragglers + return; + } + } + } catch (InterruptedException unexpected) { + throw new AssertionError("unexpected InterruptedException"); + } + throw new AssertionError("failed to do a \"full\" gc"); + } + + static void gcAwait(BooleanSupplier s) { + for (int i = 0; i < 10; i++) { + if (s.getAsBoolean()) + return; + forceFullGc(); + } + throw new AssertionError("failed to satisfy condition"); + } + /* * Called by JNI_OnUnload when the native library is unloaded */ @@ -52,19 +84,12 @@ public static void main(String... args) throws Exception { setup(); - for (int count=1; count <= 5; count++) { + for (int count = 1; count <= 5; count++) { // create a class loader and load a native library runTest(); - // unloading the class loader and native library - System.gc(); - // give Cleaner thread a chance to unload the native library - Thread.sleep(100); - - // unloadedCount is incremented when the native library is unloaded - if (count != unloadedCount) { - throw new RuntimeException("Expected unloaded=" + count + - " but got=" + unloadedCount); - } + + final int finalCount = count; + gcAwait(() -> unloadedCount == finalCount); } }