8342659: Test vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java failed: Class nsk.share.jdi.TestClass1 was not unloaded

Co-authored-by: Chris Plummer <cjplummer@openjdk.org>
Reviewed-by: sspitsyn, cjplummer
This commit is contained in:
Albert Mingkun Yang 2025-10-17 09:02:09 +00:00
parent 9b9559a2e3
commit e62a7fa383
2 changed files with 17 additions and 46 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2025, 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
@ -28,7 +28,7 @@
package nsk.share;
import java.lang.ref.Cleaner;
import java.lang.ref.PhantomReference;
import java.util.*;
import nsk.share.gc.gp.*;
import nsk.share.test.ExecutionController;
@ -77,19 +77,9 @@ public class ClassUnloader {
public static final String INTERNAL_CLASS_LOADER_NAME = "nsk.share.CustomClassLoader";
/**
* Whole amount of time in milliseconds to wait for class loader to be reclaimed.
* Phantom reference to the class loader.
*/
private static final int WAIT_TIMEOUT = 15000;
/**
* Sleep time in milliseconds for the loop waiting for the class loader to be reclaimed.
*/
private static final int WAIT_DELTA = 1000;
/**
* Has class loader been reclaimed or not.
*/
volatile boolean is_reclaimed = false;
private PhantomReference<Object> customClassLoaderPhantomRef = null;
/**
* Current class loader used for loading classes.
@ -101,6 +91,14 @@ public class ClassUnloader {
*/
private Vector<Class<?>> classObjects = new Vector<Class<?>>();
/**
* Has class loader been reclaimed or not.
*/
private boolean isClassLoaderReclaimed() {
return customClassLoaderPhantomRef != null
&& customClassLoaderPhantomRef.refersTo(null);
}
/**
* Class object of the first class been loaded with current class loader.
* To get the rest loaded classes use <code>getLoadedClass(int)</code>.
@ -138,8 +136,7 @@ public class ClassUnloader {
customClassLoader = new CustomClassLoader();
classObjects.removeAllElements();
// Register a Cleaner to inform us when the class loader has been reclaimed.
Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } );
customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null);
return customClassLoader;
}
@ -154,8 +151,7 @@ public class ClassUnloader {
this.customClassLoader = customClassLoader;
classObjects.removeAllElements();
// Register a Cleaner to inform us when the class loader has been reclaimed.
Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } );
customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null);
}
/**
@ -244,32 +240,15 @@ public class ClassUnloader {
*/
public boolean unloadClass(ExecutionController stresser) {
is_reclaimed = false;
// free references to class and class loader to be able for collecting by GC
long waitTimeout = (customClassLoader == null) ? 0 : WAIT_TIMEOUT;
classObjects.removeAllElements();
customClassLoader = null;
// force class unloading by eating memory pool
eatMemory(stresser);
// give GC chance to run and wait for receiving reclaim notification
long timeToFinish = System.currentTimeMillis() + waitTimeout;
while (!is_reclaimed && System.currentTimeMillis() < timeToFinish) {
if (!stresser.continueExecution()) {
return false;
}
try {
// suspend thread for a while
Thread.sleep(WAIT_DELTA);
} catch (InterruptedException e) {
throw new Failure("Unexpected InterruptedException while class unloading: " + e);
}
}
// force GC to unload marked class loader and its classes
if (is_reclaimed) {
if (isClassLoaderReclaimed()) {
Runtime.getRuntime().gc();
return true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2025, 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
@ -149,19 +149,11 @@ public class AbstractDebuggeeTest {
}
}
public static final int MAX_UNLOAD_ATTEMPS = 5;
public void unloadTestClass(String className, boolean expectedUnloadingResult) {
ClassUnloader classUnloader = loadedClasses.get(className);
int unloadAttemps = 0;
if (classUnloader != null) {
boolean wasUnloaded = false;
while (!wasUnloaded && (unloadAttemps++ < MAX_UNLOAD_ATTEMPS)) {
wasUnloaded = classUnloader.unloadClass();
}
boolean wasUnloaded = classUnloader.unloadClass();
if (wasUnloaded)
loadedClasses.remove(className);