8287596: Reorg jdk.test.lib.util.ForceGC
Reviewed-by: rriggs
This commit is contained in:
parent
cc2b792704
commit
82a8bd7e92
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,8 +30,8 @@ import java.io.ObjectStreamField;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
|
||||
import jdk.test.lib.util.ForceGC;
|
||||
|
||||
@ -54,15 +54,14 @@ public class TestOSCClassLoaderLeak {
|
||||
objectStreamClass_MemoryLeakExample.toString();
|
||||
|
||||
WeakReference<Object> myOwnClassLoaderWeakReference = new WeakReference<>(myOwnClassLoader);
|
||||
assertNotNull(myOwnClassLoaderWeakReference.get());
|
||||
assertFalse(myOwnClassLoaderWeakReference.refersTo(null));
|
||||
objectStreamClass_MemoryLeakExample = null;
|
||||
myOwnClassLoader = null;
|
||||
loadClass = null;
|
||||
con = null;
|
||||
assertNotNull(myOwnClassLoaderWeakReference.get());
|
||||
assertFalse(myOwnClassLoaderWeakReference.refersTo(null));
|
||||
|
||||
ForceGC gc = new ForceGC();
|
||||
assertTrue(gc.await(() -> myOwnClassLoaderWeakReference.get() == null));
|
||||
assertTrue(ForceGC.wait(() -> myOwnClassLoaderWeakReference.refersTo(null)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -152,8 +152,7 @@ public class LoadLibraryUnload {
|
||||
clazz = null;
|
||||
threads = null;
|
||||
exceptions.clear();
|
||||
ForceGC gc = new ForceGC();
|
||||
if (!gc.await(() -> wClass.refersTo(null))) {
|
||||
if (!ForceGC.wait(() -> wClass.refersTo(null))) {
|
||||
throw new RuntimeException("Class1 hasn't been GC'ed");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -66,9 +66,8 @@ public class NativeLibraryTest {
|
||||
// Unload the class loader and native library, and give the Cleaner
|
||||
// thread a chance to unload the native library.
|
||||
// unloadedCount is incremented when the native library is unloaded.
|
||||
ForceGC gc = new ForceGC();
|
||||
final int finalCount = count;
|
||||
if (!gc.await(() -> finalCount == unloadedCount)) {
|
||||
if (!ForceGC.wait(() -> finalCount == unloadedCount)) {
|
||||
throw new RuntimeException("Expected unloaded=" + count +
|
||||
" but got=" + unloadedCount);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -214,18 +214,15 @@ public class UnloadingTest {
|
||||
}
|
||||
|
||||
void unload() {
|
||||
// Force garbage collection to trigger unloading of class loader and native library
|
||||
ForceGC gc = new ForceGC();
|
||||
assertTrue(gc.await(() -> weakRef.get() == null));
|
||||
|
||||
if (weakRef.get() != null) {
|
||||
// Force garbage collection to trigger unloading of class loader
|
||||
// and native library.
|
||||
if (!ForceGC.wait(() -> weakRef.refersTo(null))) {
|
||||
throw new RuntimeException("loader " + " not unloaded!");
|
||||
}
|
||||
}
|
||||
|
||||
boolean tryUnload() {
|
||||
ForceGC gc = new ForceGC();
|
||||
return gc.await(() -> weakRef.get() == null);
|
||||
return ForceGC.wait(() -> weakRef.refersTo(null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -107,9 +107,7 @@ public class ReflectionCallerCacheTest {
|
||||
WeakReference<?> weakLoader = loadAndRunClass(classname);
|
||||
|
||||
// Force garbage collection to trigger unloading of class loader
|
||||
new ForceGC().await(() -> weakLoader.get() == null);
|
||||
|
||||
if (weakLoader.get() != null) {
|
||||
if (!ForceGC.wait(() -> weakLoader.refersTo(null))) {
|
||||
throw new RuntimeException("Class " + classname + " not unloaded!");
|
||||
}
|
||||
}
|
||||
|
@ -49,8 +49,7 @@ public final class CheckCleanerBound {
|
||||
// Check if the object has been collected. The collection will not
|
||||
// happen if the cleaner implementation in PasswordCallback is bound
|
||||
// to the PasswordCallback object.
|
||||
ForceGC gc = new ForceGC();
|
||||
if (!gc.await(() -> weakRef.get() == null)) {
|
||||
if (!ForceGC.wait(() -> weakRef.refersTo(null))) {
|
||||
throw new RuntimeException(
|
||||
"PasswordCallback object is not released");
|
||||
}
|
||||
|
@ -54,8 +54,7 @@ public final class GssContextCleanup {
|
||||
context = null;
|
||||
|
||||
// Check if the object has been collected.
|
||||
ForceGC gc = new ForceGC();
|
||||
if (!gc.await(() -> weakRef.get() == null)) {
|
||||
if (!ForceGC.wait(() -> weakRef.refersTo(null))) {
|
||||
throw new RuntimeException("GSSContext object is not released");
|
||||
}
|
||||
}
|
||||
|
@ -55,8 +55,7 @@ public final class GssNameCleanup {
|
||||
name = null;
|
||||
|
||||
// Check if the object has been collected.
|
||||
ForceGC gc = new ForceGC();
|
||||
if (!gc.await(() -> weakRef.get() == null)) {
|
||||
if (!ForceGC.wait(() -> weakRef.refersTo(null))) {
|
||||
throw new RuntimeException("GSSName object is not released");
|
||||
}
|
||||
} catch (GSSException gsse) {
|
||||
|
@ -89,10 +89,8 @@ public class MultipleLogins {
|
||||
Security.removeProvider(providers[i].getName());
|
||||
providers[i] = null;
|
||||
|
||||
ForceGC gc = new ForceGC();
|
||||
int finalI = i;
|
||||
gc.await(() -> weakRef[finalI].get() == null);
|
||||
if (!weakRef[i].refersTo(null)) {
|
||||
if (!ForceGC.wait(() -> weakRef[finalI].refersTo(null))) {
|
||||
throw new RuntimeException("Expected SunPKCS11 Provider to be GC'ed..");
|
||||
}
|
||||
}
|
||||
|
@ -23,68 +23,56 @@
|
||||
|
||||
package jdk.test.lib.util;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
/**
|
||||
* Utility class to invoke System.gc()
|
||||
*/
|
||||
public class ForceGC {
|
||||
private final static Cleaner cleaner = Cleaner.create();
|
||||
|
||||
private final CountDownLatch cleanerInvoked;
|
||||
private Object o;
|
||||
private int gcCount = 0;
|
||||
|
||||
public ForceGC() {
|
||||
this.o = new Object();
|
||||
this.cleanerInvoked = new CountDownLatch(1);
|
||||
cleaner.register(o, cleanerInvoked::countDown);
|
||||
}
|
||||
|
||||
private void doit(int iter) {
|
||||
try {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.gc();
|
||||
gcCount++;
|
||||
if (cleanerInvoked.await(100L, TimeUnit.MILLISECONDS)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException unexpected) {
|
||||
throw new AssertionError("unexpected InterruptedException");
|
||||
}
|
||||
}
|
||||
// The jtreg testing timeout factor.
|
||||
private static final double TIMEOUT_FACTOR = Double.valueOf(
|
||||
System.getProperty("test.timeout.factor", "1.0"));
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until the {@code BooleanSupplier} returns true,
|
||||
* unless the thread is interrupted or a predefined waiting time elapses.
|
||||
* Causes the current thread to wait until the {@code booleanSupplier}
|
||||
* returns true, or a specific waiting time elapses. The waiting time
|
||||
* is 1 second scaled with the jtreg testing timeout factor.
|
||||
*
|
||||
* @param s boolean supplier
|
||||
* @return true if the {@code BooleanSupplier} returns true and false if
|
||||
* the predefined waiting time elapsed before the count reaches zero.
|
||||
* @throws InterruptedException if the current thread is interrupted while waiting
|
||||
* @param booleanSupplier boolean supplier
|
||||
* @return true if the {@code booleanSupplier} returns true, or false
|
||||
* if did not complete after the specific waiting time.
|
||||
*/
|
||||
public boolean await(BooleanSupplier s) {
|
||||
o = null; // Keep reference to Object until now, to ensure the Cleaner
|
||||
// doesn't count down the latch before await() is called.
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (s.getAsBoolean()) {
|
||||
System.out.println("ForceGC condition met after System.gc() " + gcCount + " times");
|
||||
public static boolean wait(BooleanSupplier booleanSupplier) {
|
||||
ReferenceQueue<Object> queue = new ReferenceQueue<>();
|
||||
Object obj = new Object();
|
||||
PhantomReference<Object> ref = new PhantomReference<>(obj, queue);
|
||||
obj = null;
|
||||
Reference.reachabilityFence(obj);
|
||||
Reference.reachabilityFence(ref);
|
||||
|
||||
int retries = (int)(Math.round(1000L * TIMEOUT_FACTOR) / 200);
|
||||
for (; retries >= 0; retries--) {
|
||||
if (booleanSupplier.getAsBoolean()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
doit(i);
|
||||
System.gc();
|
||||
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
throw new AssertionError("unexpected interrupted sleep", e);
|
||||
// The remove() will always block for the specified milliseconds
|
||||
// if the reference has already been removed from the queue.
|
||||
// But it is fine. For most cases, the 1st GC is sufficient
|
||||
// to trigger and complete the cleanup.
|
||||
queue.remove(200L);
|
||||
} catch (InterruptedException ie) {
|
||||
// ignore, the loop will try again
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("ForceGC condition not met after System.gc() " + gcCount + " times");
|
||||
return false;
|
||||
return booleanSupplier.getAsBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user