Skip to content

Commit

Permalink
8287596: Reorg jdk.test.lib.util.ForceGC
Browse files Browse the repository at this point in the history
Reviewed-by: rriggs
  • Loading branch information
XueleiFan committed Jul 6, 2022
1 parent cc2b792 commit 82a8bd7
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 79 deletions.
11 changes: 5 additions & 6 deletions test/jdk/java/io/ObjectStreamClass/TestOSCClassLoaderLeak.java
@@ -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
Expand Down Expand Up @@ -30,8 +30,8 @@
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;

Expand All @@ -54,15 +54,14 @@ public void testClassLoaderLeak() throws Exception {
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)));
}
}

Expand Down
@@ -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.
*
Expand Down Expand Up @@ -152,8 +152,7 @@ public static void main(String[] args) throws Exception {
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");
}
}
Expand Down
@@ -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
Expand Down Expand Up @@ -66,9 +66,8 @@ public static void main(String... args) throws Exception {
// 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);
}
Expand Down
13 changes: 5 additions & 8 deletions test/jdk/java/lang/invoke/defineHiddenClass/UnloadingTest.java
@@ -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
Expand Down Expand Up @@ -214,18 +214,15 @@ private HiddenClassUnloader(Class<?> hc) {
}

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));
}
}

Expand Down
@@ -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
Expand Down Expand Up @@ -107,9 +107,7 @@ private void load(String classname) throws Exception {
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!");
}
}
Expand Down
Expand Up @@ -49,8 +49,7 @@ public static void main(String[] args) throws Exception {
// 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");
}
Expand Down
3 changes: 1 addition & 2 deletions test/jdk/sun/security/jgss/GssContextCleanup.java
Expand Up @@ -54,8 +54,7 @@ public static void main(String[] args) throws Exception {
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");
}
}
Expand Down
3 changes: 1 addition & 2 deletions test/jdk/sun/security/jgss/GssNameCleanup.java
Expand Up @@ -55,8 +55,7 @@ public static void main(String[] args) throws Exception {
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) {
Expand Down
4 changes: 1 addition & 3 deletions test/jdk/sun/security/pkcs11/Provider/MultipleLogins.java
Expand Up @@ -89,10 +89,8 @@ public static void main(String[] args) throws Exception {
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..");
}
}
Expand Down
80 changes: 34 additions & 46 deletions test/lib/jdk/test/lib/util/ForceGC.java
Expand Up @@ -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();
}
}

1 comment on commit 82a8bd7

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.