8307824: Clean up Finalizable.java and finalize terminology in vmTestbase/nsk/share

Reviewed-by: sspitsyn, cjplummer
This commit is contained in:
Leonid Mesnik 2024-06-04 19:18:41 +00:00
parent a706e35b12
commit 244f6ac222
10 changed files with 43 additions and 290 deletions

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -33,22 +33,23 @@ import nsk.share.jdi.AbstractJDIDebuggee;
*/ */
public class VMOutOfMemoryException001t extends AbstractJDIDebuggee { public class VMOutOfMemoryException001t extends AbstractJDIDebuggee {
public static int[] reserverdMemory = new int[1024 * 1024];
public static void main(String args[]) { public static void main(String args[]) {
new VMOutOfMemoryException001t().doTest(args); new VMOutOfMemoryException001t().doTest(args);
} }
// Just call normal doTest() function, but hide any OutOfMemoryErrors. // Just call normal doTest() function, but hide any OutOfMemoryErrors.
@Override
public void doTest() { public void doTest() {
boolean isOutOfMemory = false; boolean isOutOfMemory = false;
try { try {
super.doTest(); super.doTest();
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
// Don't log anything. We are out of memory.
// A println is likely to genereate a new OutOfMemoryError
isOutOfMemory = true; isOutOfMemory = true;
reserverdMemory = null;
log.display("Got expected OOME.");
} }
// Normally the super class handles the return value. // Normally the super class handles the return value.
// If we got here after an OutOfMemoryError, we consider the test passed. // If we got here after an OutOfMemoryError, we consider the test passed.
if (isOutOfMemory && callExit) { if (isOutOfMemory && callExit) {

@ -1,65 +0,0 @@
/*
* Copyright (c) 2001, 2023, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package nsk.share;
import java.lang.ref.Cleaner;
/**
* Finalizable interface allows <tt>Finalizer</tt> to perform finalization of an object.
* Each object that requires finalization at VM shutdown time should implement this
* interface and call the <tt>registerCleanup</tt> to activate a <tt>Finalizer</tt> hook.
*
* @see Finalizer
*/
public interface Finalizable {
/**
* This method will be implemented by FinalizableObject and is called in <tt>finalizeAtExit</tt>.
*
* @see Finalizer
*/
public void cleanup();
/**
* This method will be invoked by <tt>Finalizer</tt> when virtual machine
* shuts down.
*
* @throws Throwable if any throwable exception thrown during finalization
*/
default public void finalizeAtExit() throws Throwable {
cleanup();
}
/**
* This method will register a cleanup method and create an instance of Finalizer
* to register the object for finalization at VM exit.
*
* @see Finalizer
*/
default public void registerCleanup() {
Finalizer finalizer = new Finalizer(this);
finalizer.activate();
Cleaner.create().register(this, () -> cleanup());
}
}

@ -1,40 +0,0 @@
/*
* Copyright (c) 2001, 2023, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package nsk.share;
/**
* This class is a simple example of finalizable object, that
* implements interface <code>Finalizable</code>.
*
* @see Finalizable
* @see Finalizer
*/
public class FinalizableObject implements Finalizable {
/**
* Subclasses should override this method to provide the specific
* cleanup actions that they need.
*/
public void cleanup() {}
}

@ -1,133 +0,0 @@
/*
* Copyright (c) 2001, 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package nsk.share;
import java.util.Stack;
/**
* Finalizer performs object finalization when virtual mashine shuts down.
* Finalizer is a thread that acts as a VM shutdown hook.
* This thread will be activated as VM shuts down because of
* invocation of <code>exit()</code> or termination. After activation
* Finalizer just calls <code>finalizeAtExit()</code> method of the specified object.
* The finalizable object should implement interface <code>Finalizable</code>.
*
* @see Finalizable
*/
public class Finalizer {
/** Finalizer thread to register as a VM shutdown hook. */
private static FinalizerThread finalizerThread = null;
/** An object to finalize. */
private Finalizable object;
/**
* Create finalizer for the specified object.
*/
public Finalizer(Finalizable object) {
this.object = object;
}
/**
* Register finalizer for finalization at VM shutdown.
*/
public void activate() {
if (finalizerThread == null) {
finalizerThread = new FinalizerThread("FinalizerThread for Finalizable objects");
finalizerThread.activate();
}
finalizerThread.add(object);
}
/**
* Unregister finalizer for finalization at VM shutdown.
*/
public void deactivate() {
if (finalizerThread == null)
return;
finalizerThread.remove(object);
}
/**
* Static inner thread that is registered as a VM shutdown hook
* and performs finalization of all registered finalizable objects.
*/
private static class FinalizerThread extends Thread {
/** Stack of objects registered for finalization. */
private Stack<Object> objects = new Stack<Object>();
/** Make new instance of FinalizerThread with given thread name. */
public FinalizerThread(String threadName) {
super(threadName);
}
/**
* Push an object to the stack of registered objects.
*/
public void add(Finalizable object) {
objects.push(object);
}
/**
* Remove an object from the stack of registered objects.
*/
public void remove(Finalizable object) {
objects.remove(object);
}
/**
* Register finalizer thread as a VM shutdown hook.
*/
public void activate() {
Runtime.getRuntime().addShutdownHook( this );
}
/**
* Unregister finalizer thread as a VM shutdown hook.
*/
public void deactivate() {
Runtime.getRuntime().removeShutdownHook( this );
}
/**
* Pop all registered objects from the stack and finalize them.
*/
public void run() {
while (!objects.empty()) {
Finalizable object = (Finalizable)objects.pop();
try {
object.finalizeAtExit();
} catch (ThreadDeath e) {
throw e;
} catch (Throwable ex) {
ex.printStackTrace();
}
}
}
} // end of FinalizerThread
} // end of Finalizer

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -41,11 +41,6 @@ public final class MainWrapper {
String[] classArgs = new String[args.length - 2]; String[] classArgs = new String[args.length - 2];
System.arraycopy(args, 2, classArgs, 0, args.length - 2); System.arraycopy(args, 2, classArgs, 0, args.length - 2);
// It is needed to register finalizer thread in default thread group
// So FinalizerThread thread can't be in virtual threads group
FinalizableObject finalizableObject = new FinalizableObject();
finalizableObject.registerCleanup();
// Some tests use this property to understand if virtual threads are used // Some tests use this property to understand if virtual threads are used
System.setProperty("test.thread.factory", wrapperName); System.setProperty("test.thread.factory", wrapperName);

@ -54,17 +54,23 @@ public class DummyTargetApplication {
} }
public void runTargetApplication() { public void runTargetApplication() {
pipe = SocketIOPipe.createClientIOPipe(log, argParser.getPort(), 0); try {
log.display("Sending signal '" + AODTestRunner.SIGNAL_READY_FOR_ATTACH + "'"); pipe = SocketIOPipe.createClientIOPipe(log, argParser.getPort(), 0);
pipe.println(AODTestRunner.SIGNAL_READY_FOR_ATTACH); log.display("Sending signal '" + AODTestRunner.SIGNAL_READY_FOR_ATTACH + "'");
pipe.println(AODTestRunner.SIGNAL_READY_FOR_ATTACH);
targetApplicationActions(); targetApplicationActions();
String signal = pipe.readln(); String signal = pipe.readln();
log.display("Signal received: '" + signal + "'"); log.display("Signal received: '" + signal + "'");
if ((signal == null) || !signal.equals(AODTestRunner.SIGNAL_FINISH)) if ((signal == null) || !signal.equals(AODTestRunner.SIGNAL_FINISH))
throw new TestBug("Unexpected signal: '" + signal + "'"); throw new TestBug("Unexpected signal: '" + signal + "'");
} finally {
if (pipe != null) {
pipe.close();
}
}
} }
public static void main(String[] args) { public static void main(String[] args) {

@ -66,7 +66,7 @@ import java.util.*;
* @see nsk.share.jdi.Binder * @see nsk.share.jdi.Binder
* @see nsk.share.jdwp.Binder * @see nsk.share.jdwp.Binder
*/ */
public class DebugeeBinder extends Log.Logger implements Finalizable { public class DebugeeBinder extends Log.Logger {
private static final boolean IS_WINDOWS = System.getProperty("os.name") private static final boolean IS_WINDOWS = System.getProperty("os.name")
.toLowerCase() .toLowerCase()
@ -118,8 +118,6 @@ public class DebugeeBinder extends Log.Logger implements Finalizable {
public DebugeeBinder (DebugeeArgumentHandler argumentHandler, Log log) { public DebugeeBinder (DebugeeArgumentHandler argumentHandler, Log log) {
super(log, LOG_PREFIX); super(log, LOG_PREFIX);
this.argumentHandler = argumentHandler; this.argumentHandler = argumentHandler;
registerCleanup();
} }
/** /**
@ -546,14 +544,6 @@ public class DebugeeBinder extends Log.Logger implements Finalizable {
closePipeServerSocket(); closePipeServerSocket();
} }
/**
* Finalize binder by invoking <code>close()</code>.
*
*/
public void cleanup() {
close();
}
/** /**
* Separate thread for listening connection from <code>BindServer</code>. * Separate thread for listening connection from <code>BindServer</code>.
*/ */

@ -196,16 +196,26 @@ abstract public class DebugeeProcess {
*/ */
public int waitFor () { public int waitFor () {
long timeout = binder.getArgumentHandler().getWaitTime() * 60 * 1000; long timeout = binder.getArgumentHandler().getWaitTime() * 60 * 1000;
int exitCode = 0; int exitCode;
try { try {
exitCode = waitForDebugee(); exitCode = waitForDebugee();
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
ie.printStackTrace(log.getOutStream()); ie.printStackTrace(log.getOutStream());
throw new Failure("Caught exception while waiting for debuggee process: \n\t" + ie); throw new Failure("Caught exception while waiting for debuggee process: \n\t" + ie);
} } finally {
waitForRedirectors(timeout); try {
if (process != null) { waitForRedirectors(timeout);
process.destroy(); } finally {
if (process != null) {
process.destroy();
}
if (pipe != null) {
pipe.close();
}
if (binder != null) {
binder.close();
}
}
} }
return exitCode; return exitCode;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -72,12 +72,16 @@ public class IOPipe extends SocketIOPipe {
(long)debugee.getArgumentHandler().getWaitTime() * 60 * 1000, (long)debugee.getArgumentHandler().getWaitTime() * 60 * 1000,
true); true);
setServerSocket(debugee.getPipeServerSocket()); setServerSocket(debugee.getPipeServerSocket());
if (debugee.pipe != null) {
throw new RuntimeException("debugee pipe is already set");
}
debugee.pipe = this;
} }
/** /**
* Make general <code>IOPipe</code> object with specified parameters. * Make general <code>IOPipe</code> object with specified parameters.
*/ */
protected IOPipe(Log log, String host, int port, long timeout, boolean listening) { private IOPipe(Log log, String host, int port, long timeout, boolean listening) {
super("IOPipe", log, PIPE_LOG_PREFIX, host, port, timeout, listening); super("IOPipe", log, PIPE_LOG_PREFIX, host, port, timeout, listening);
} }

@ -62,7 +62,7 @@ import nsk.share.*;
* pipe.println(command); * pipe.println(command);
* *
*/ */
public class SocketIOPipe extends Log.Logger implements Finalizable { public class SocketIOPipe extends Log.Logger {
public static final int DEFAULT_TIMEOUT_VALUE = 1 * 60 * 1000; public static final int DEFAULT_TIMEOUT_VALUE = 1 * 60 * 1000;
@ -93,8 +93,6 @@ public class SocketIOPipe extends Log.Logger implements Finalizable {
this.timeout = timeout; this.timeout = timeout;
this.listening = listening; this.listening = listening;
this.name = name; this.name = name;
registerCleanup();
} }
/** /**
@ -106,8 +104,6 @@ public class SocketIOPipe extends Log.Logger implements Finalizable {
this.port = port; this.port = port;
this.timeout = timeout; this.timeout = timeout;
this.listening = listening; this.listening = listening;
registerCleanup();
} }
/** /**
@ -311,17 +307,6 @@ public class SocketIOPipe extends Log.Logger implements Finalizable {
return connection.getPingTimeout(); return connection.getPingTimeout();
} }
/**
* Perform finalization of the object by invoking close().
*
* This is replacement of finalize() method and is called
* when this instance becomes unreachable.
*
*/
public void cleanup() {
close();
}
/** /**
* Field 'pipeCounter' and method 'getNextPipeNumber' are used to construct unique names for SocketIOPipes * Field 'pipeCounter' and method 'getNextPipeNumber' are used to construct unique names for SocketIOPipes