mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-24 13:51:12 +00:00
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:
parent
9b9559a2e3
commit
e62a7fa383
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user