8198249: Remove deprecated Runtime::runFinalizersOnExit and System::runFinalizersOnExit

Reviewed-by: dholmes, alanb, smarks
This commit is contained in:
Mandy Chung 2018-02-23 12:10:56 -08:00
parent cfe9ad4608
commit 4bb064c62d
20 changed files with 114 additions and 500 deletions
make/mapfiles/libjava
src
hotspot/share
java.base/share
jdk.jdeps/share/classes/com/sun/tools/jdeprscan
test
hotspot/jtreg/testlibrary/jittester/conf
jdk/java/lang

@ -143,7 +143,6 @@ SUNWprivate_1.1 {
Java_java_lang_StackStreamFactory_checkStackWalkModes;
Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk;
Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames;
Java_java_lang_Shutdown_runAllFinalizers;
Java_java_lang_StrictMath_IEEEremainder;
Java_java_lang_StrictMath_acos;
Java_java_lang_StrictMath_asin;

@ -358,7 +358,6 @@
template(reference_lock_name, "lock") \
template(reference_discovered_name, "discovered") \
template(run_finalization_name, "runFinalization") \
template(run_finalizers_on_exit_name, "runFinalizersOnExit") \
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
template(loadClass_name, "loadClass") \
template(loadClassInternal_name, "loadClassInternal") \

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -542,32 +542,6 @@ oop Universe::swap_reference_pending_list(oop list) {
#undef assert_pll_locked
#undef assert_pll_ownership
static bool has_run_finalizers_on_exit = false;
void Universe::run_finalizers_on_exit() {
if (has_run_finalizers_on_exit) return;
has_run_finalizers_on_exit = true;
// Called on VM exit. This ought to be run in a separate thread.
log_trace(ref)("Callback to run finalizers on exit");
{
PRESERVE_EXCEPTION_MARK;
Klass* finalizer_klass = SystemDictionary::Finalizer_klass();
JavaValue result(T_VOID);
JavaCalls::call_static(
&result,
finalizer_klass,
vmSymbols::run_finalizers_on_exit_name(),
vmSymbols::void_method_signature(),
THREAD
);
// Ignore any pending exceptions
CLEAR_PENDING_EXCEPTION;
}
}
// initialize_vtable could cause gc if
// 1) we specified true to initialize_vtable and
// 2) this ran after gc was enabled

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -464,9 +464,6 @@ class Universe: AllStatic {
static bool should_fill_in_stack_trace(Handle throwable);
static void check_alignment(uintx size, uintx alignment, const char* name);
// Finalizer support.
static void run_finalizers_on_exit();
// Iteration
// Apply "f" to the addresses of all the direct heap pointers maintained

@ -4202,10 +4202,9 @@ void JavaThread::invoke_shutdown_hooks() {
// SystemDictionary::resolve_or_null will return null if there was
// an exception. If we cannot load the Shutdown class, just don't
// call Shutdown.shutdown() at all. This will mean the shutdown hooks
// and finalizers (if runFinalizersOnExit is set) won't be run.
// Note that if a shutdown hook was registered or runFinalizersOnExit
// was called, the Shutdown class would have already been loaded
// (Runtime.addShutdownHook and runFinalizersOnExit will load it).
// won't be run. Note that if a shutdown hook was registered,
// the Shutdown class would have already been loaded
// (Runtime.addShutdownHook will load it).
JavaValue result(T_VOID);
JavaCalls::call_static(&result,
shutdown_klass,
@ -4228,7 +4227,7 @@ void JavaThread::invoke_shutdown_hooks() {
// + Wait until we are the last non-daemon thread to execute
// <-- every thing is still working at this moment -->
// + Call java.lang.Shutdown.shutdown(), which will invoke Java level
// shutdown hooks, run finalizers if finalization-on-exit
// shutdown hooks
// + Call before_exit(), prepare for VM exit
// > run VM level shutdown hooks (they are registered through JVM_OnExit(),
// currently the only user of this mechanism is File.deleteOnExit())

@ -79,18 +79,14 @@ public class Runtime {
* serves as a status code; by convention, a nonzero status code indicates
* abnormal termination.
*
* <p> The virtual machine's shutdown sequence consists of two phases. In
* the first phase all registered {@link #addShutdownHook shutdown hooks},
* if any, are started in some unspecified order and allowed to run
* concurrently until they finish. In the second phase all uninvoked
* finalizers are run if {@link #runFinalizersOnExit finalization-on-exit}
* has been enabled. Once this is done the virtual machine {@link #halt halts}.
* <p> All registered {@linkplain #addShutdownHook shutdown hooks}, if any,
* are started in some unspecified order and allowed to run concurrently
* until they finish. Once this is done the virtual machine
* {@linkplain #halt halts}.
*
* <p> If this method is invoked after the virtual machine has begun its
* shutdown sequence then if shutdown hooks are being run this method will
* block indefinitely. If shutdown hooks have already been run and on-exit
* finalization has been enabled then this method halts the virtual machine
* with the given status code if the status is nonzero; otherwise, it
* <p> If this method is invoked after all shutdown hooks have already
* been run and the status is nonzero then this method halts the
* virtual machine with the given status code. Otherwise, this method
* blocks indefinitely.
*
* <p> The {@link System#exit(int) System.exit} method is the
@ -109,7 +105,6 @@ public class Runtime {
* @see java.lang.SecurityManager#checkExit(int)
* @see #addShutdownHook
* @see #removeShutdownHook
* @see #runFinalizersOnExit
* @see #halt(int)
*/
public void exit(int status) {
@ -142,10 +137,9 @@ public class Runtime {
* thread. When the virtual machine begins its shutdown sequence it will
* start all registered shutdown hooks in some unspecified order and let
* them run concurrently. When all the hooks have finished it will then
* run all uninvoked finalizers if finalization-on-exit has been enabled.
* Finally, the virtual machine will halt. Note that daemon threads will
* continue to run during the shutdown sequence, as will non-daemon threads
* if shutdown was initiated by invoking the {@link #exit exit} method.
* halt. Note that daemon threads will continue to run during the shutdown
* sequence, as will non-daemon threads if shutdown was initiated by
* invoking the {@link #exit exit} method.
*
* <p> Once the shutdown sequence has begun it can be stopped only by
* invoking the {@link #halt halt} method, which forcibly
@ -255,10 +249,9 @@ public class Runtime {
*
* <p> This method should be used with extreme caution. Unlike the
* {@link #exit exit} method, this method does not cause shutdown
* hooks to be started and does not run uninvoked finalizers if
* finalization-on-exit has been enabled. If the shutdown sequence has
* already been initiated then this method does not wait for any running
* shutdown hooks or finalizers to finish their work.
* hooks to be started. If the shutdown sequence has already been
* initiated then this method does not wait for any running
* shutdown hooks to finish their work.
*
* @param status
* Termination status. By convention, a nonzero status code
@ -285,46 +278,6 @@ public class Runtime {
Shutdown.halt(status);
}
/**
* Enable or disable finalization on exit; doing so specifies that the
* finalizers of all objects that have finalizers that have not yet been
* automatically invoked are to be run before the Java runtime exits.
* By default, finalization on exit is disabled.
*
* <p>If there is a security manager,
* its {@code checkExit} method is first called
* with 0 as its argument to ensure the exit is allowed.
* This could result in a SecurityException.
*
* @param value true to enable finalization on exit, false to disable
* @deprecated This method is inherently unsafe. It may result in
* finalizers being called on live objects while other threads are
* concurrently manipulating those objects, resulting in erratic
* behavior or deadlock.
* This method is subject to removal in a future version of Java SE.
*
* @throws SecurityException
* if a security manager exists and its {@code checkExit}
* method doesn't allow the exit.
*
* @see java.lang.Runtime#exit(int)
* @see java.lang.Runtime#gc()
* @see java.lang.SecurityManager#checkExit(int)
* @since 1.1
*/
@Deprecated(since="1.2", forRemoval=true)
public static void runFinalizersOnExit(boolean value) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
try {
security.checkExit(0);
} catch (SecurityException e) {
throw new SecurityException("runFinalizersOnExit");
}
}
Shutdown.setRunFinalizersOnExit(value);
}
/**
* Executes the specified string command in a separate process.
*

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
@ -26,35 +26,33 @@
package java.lang;
import jdk.internal.misc.VM;
/**
* Package-private utility class containing data structures and logic
* governing the virtual-machine shutdown sequence.
*
* @author Mark Reinhold
* @since 1.3
*
* @see java.io.Console
* @see ApplicationShutdownHooks
* @see java.io.DeleteOnExitHook
*/
class Shutdown {
/* Shutdown state */
private static final int RUNNING = 0;
private static final int HOOKS = 1;
private static final int FINALIZERS = 2;
private static int state = RUNNING;
/* Should we run all finalizers upon exit? */
private static boolean runFinalizersOnExit = false;
// The system shutdown hooks are registered with a predefined slot.
// The list of shutdown hooks is as follows:
// (0) Console restore hook
// (1) Application hooks
// (1) ApplicationShutdownHooks that invokes all registered application
// shutdown hooks and waits until they finish
// (2) DeleteOnExit hook
private static final int MAX_SYSTEM_HOOKS = 10;
private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS];
// the index of the currently running shutdown hook to the hooks array
private static int currentRunningHook = 0;
private static int currentRunningHook = -1;
/* The preceding static fields are protected by this lock */
private static class Lock { };
@ -63,17 +61,9 @@ class Shutdown {
/* Lock object for the native halt method */
private static Object haltLock = new Lock();
/* Invoked by Runtime.runFinalizersOnExit */
static void setRunFinalizersOnExit(boolean run) {
synchronized (lock) {
runFinalizersOnExit = run;
}
}
/**
* Add a new shutdown hook. Checks the shutdown state and the hook itself,
* but does not do any security checks.
* Add a new system shutdown hook. Checks the shutdown state and
* the hook itself, but does not do any security checks.
*
* The registerShutdownInProgress parameter should be false except
* registering the DeleteOnExitHook since the first file may
@ -92,15 +82,18 @@ class Shutdown {
* already passes the given slot
*/
static void add(int slot, boolean registerShutdownInProgress, Runnable hook) {
if (slot < 0 || slot >= MAX_SYSTEM_HOOKS) {
throw new IllegalArgumentException("Invalid slot: " + slot);
}
synchronized (lock) {
if (hooks[slot] != null)
throw new InternalError("Shutdown hook at slot " + slot + " already registered");
if (!registerShutdownInProgress) {
if (state > RUNNING)
if (currentRunningHook >= 0)
throw new IllegalStateException("Shutdown in progress");
} else {
if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook))
if (VM.isShutdown() || slot <= currentRunningHook)
throw new IllegalStateException("Shutdown in progress");
}
@ -108,9 +101,23 @@ class Shutdown {
}
}
/* Run all registered shutdown hooks
/* Run all system shutdown hooks.
*
* The system shutdown hooks are run in the thread synchronized on
* Shutdown.class. Other threads calling Runtime::exit, Runtime::halt
* or JNI DestroyJavaVM will block indefinitely.
*
* ApplicationShutdownHooks is registered as one single hook that starts
* all application shutdown hooks and waits until they finish.
*/
private static void runHooks() {
synchronized (lock) {
/* Guard against the possibility of a daemon thread invoking exit
* after DestroyJavaVM initiates the shutdown sequence
*/
if (VM.isShutdown()) return;
}
for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
try {
Runnable hook;
@ -121,13 +128,16 @@ class Shutdown {
hook = hooks[i];
}
if (hook != null) hook.run();
} catch(Throwable t) {
} catch (Throwable t) {
if (t instanceof ThreadDeath) {
ThreadDeath td = (ThreadDeath)t;
throw td;
}
}
}
// set shutdown state
VM.shutdown();
}
/* The halt method is synchronized on the halt lock
@ -142,74 +152,22 @@ class Shutdown {
static native void halt0(int status);
/* Wormhole for invoking java.lang.ref.Finalizer.runAllFinalizers */
private static native void runAllFinalizers();
/* The actual shutdown sequence is defined here.
*
* If it weren't for runFinalizersOnExit, this would be simple -- we'd just
* run the hooks and then halt. Instead we need to keep track of whether
* we're running hooks or finalizers. In the latter case a finalizer could
* invoke exit(1) to cause immediate termination, while in the former case
* any further invocations of exit(n), for any n, simply stall. Note that
* if on-exit finalizers are enabled they're run iff the shutdown is
* initiated by an exit(0); they're never run on exit(n) for n != 0 or in
* response to SIGINT, SIGTERM, etc.
*/
private static void sequence() {
synchronized (lock) {
/* Guard against the possibility of a daemon thread invoking exit
* after DestroyJavaVM initiates the shutdown sequence
*/
if (state != HOOKS) return;
}
runHooks();
boolean rfoe;
synchronized (lock) {
state = FINALIZERS;
rfoe = runFinalizersOnExit;
}
if (rfoe) runAllFinalizers();
}
/* Invoked by Runtime.exit, which does all the security checks.
* Also invoked by handlers for system-provided termination events,
* which should pass a nonzero status code.
*/
static void exit(int status) {
boolean runMoreFinalizers = false;
synchronized (lock) {
if (status != 0) runFinalizersOnExit = false;
switch (state) {
case RUNNING: /* Initiate shutdown */
state = HOOKS;
break;
case HOOKS: /* Stall and halt */
break;
case FINALIZERS:
if (status != 0) {
/* Halt immediately on nonzero status */
halt(status);
} else {
/* Compatibility with old behavior:
* Run more finalizers and then halt
*/
runMoreFinalizers = runFinalizersOnExit;
}
break;
if (status != 0 && VM.isShutdown()) {
/* Halt immediately on nonzero status */
halt(status);
}
}
if (runMoreFinalizers) {
runAllFinalizers();
halt(status);
}
synchronized (Shutdown.class) {
/* Synchronize on the class object, causing any other thread
* that attempts to initiate shutdown to stall indefinitely
*/
sequence();
runHooks();
halt(status);
}
}
@ -220,18 +178,8 @@ class Shutdown {
* actually halt the VM.
*/
static void shutdown() {
synchronized (lock) {
switch (state) {
case RUNNING: /* Initiate shutdown */
state = HOOKS;
break;
case HOOKS: /* Stall and then return */
case FINALIZERS:
break;
}
}
synchronized (Shutdown.class) {
sequence();
runHooks();
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 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
@ -1765,38 +1765,6 @@ public final class System {
Runtime.getRuntime().runFinalization();
}
/**
* Enable or disable finalization on exit; doing so specifies that the
* finalizers of all objects that have finalizers that have not yet been
* automatically invoked are to be run before the Java runtime exits.
* By default, finalization on exit is disabled.
*
* <p>If there is a security manager,
* its <code>checkExit</code> method is first called
* with 0 as its argument to ensure the exit is allowed.
* This could result in a SecurityException.
*
* @deprecated This method is inherently unsafe. It may result in
* finalizers being called on live objects while other threads are
* concurrently manipulating those objects, resulting in erratic
* behavior or deadlock.
* This method is subject to removal in a future version of Java SE.
* @param value indicating enabling or disabling of finalization
* @throws SecurityException
* if a security manager exists and its <code>checkExit</code>
* method doesn't allow the exit.
*
* @see java.lang.Runtime#exit(int)
* @see java.lang.Runtime#gc()
* @see java.lang.SecurityManager#checkExit(int)
* @since 1.1
*/
@Deprecated(since="1.2", forRemoval=true)
@SuppressWarnings("removal")
public static void runFinalizersOnExit(boolean value) {
Runtime.runFinalizersOnExit(value);
}
/**
* Loads the native library specified by the filename argument. The filename
* argument must be an absolute path name.

@ -1,6 +1,6 @@
<!doctype html>
<!--
Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2005, 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
@ -346,19 +346,6 @@ deprecated. If it were implemented, it would be deadlock-prone in
the manner of <code>Thread.suspend</code>. (In fact, it is roughly
equivalent to <code>Thread.suspend</code> without the possibility
of a subsequent <code>Thread.resume</code>.)
<hr>
<h3>Why is <code>Runtime.runFinalizersOnExit</code>
deprecated?</h3>
Because it is inherently unsafe. It may result in finalizers being
called on live objects while other threads are concurrently
manipulating those objects, resulting in erratic behavior or
deadlock. While this problem could be prevented if the class whose
objects are being finalized were coded to "defend against" this
call, most programmers do <i>not</i> defend against it. They assume
that an object is dead at the time that its finalizer is called.
<p>Further, the call is not "thread-safe" in the sense that it sets
a VM-global flag. This forces <i>every</i> class with a finalizer
to defend against the finalization of live objects!</p>
<p><!-- Body text ends here --></p>
</body>
</html>

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -66,7 +66,7 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
new Finalizer(finalizee);
}
private void deregisterAndRunFinalizer(JavaLangAccess jla) {
private void runFinalizer(JavaLangAccess jla) {
synchronized (lock) {
if (this.next == this) // already finalized
return;
@ -80,17 +80,14 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
this.prev = null;
this.next = this; // mark as finalized
}
runFinalizer(jla);
}
private void runFinalizer(JavaLangAccess jla) {
try {
Object finalizee = this.get();
if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
jla.invokeFinalize(finalizee);
/* Clear stack slot containing this variable, to decrease
the chances of false retention with a conservative GC */
// Clear stack slot containing this variable, to decrease
// the chances of false retention with a conservative GC
finalizee = null;
}
} catch (Throwable x) { }
@ -98,17 +95,14 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
}
/* Create a privileged secondary finalizer thread in the system thread
group for the given Runnable, and wait for it to complete.
This method is used by both runFinalization and runFinalizersOnExit.
The former method invokes all pending finalizers, while the latter
invokes all uninvoked finalizers if on-exit finalization has been
enabled.
These two methods could have been implemented by offloading their work
to the regular finalizer thread and waiting for that thread to finish.
The advantage of creating a fresh thread, however, is that it insulates
invokers of these methods from a stalled or deadlocked finalizer thread.
* group for the given Runnable, and wait for it to complete.
*
* This method is used by runFinalization.
*
* It could have been implemented by offloading the work to the
* regular finalizer thread and waiting for that thread to finish.
* The advantage of creating a fresh thread, however, is that it insulates
* invokers of that method from a stalled or deadlocked finalizer thread.
*/
private static void forkSecondaryFinalizer(final Runnable proc) {
AccessController.doPrivileged(
@ -144,40 +138,11 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
running = true;
for (Finalizer f; (f = (Finalizer)queue.poll()) != null; )
f.deregisterAndRunFinalizer(jla);
f.runFinalizer(jla);
}
});
}
/* Invoked by java.lang.Shutdown */
static void runAllFinalizers() {
if (VM.initLevel() == 0) {
return;
}
forkSecondaryFinalizer(new Runnable() {
private volatile boolean running;
public void run() {
// in case of recursive call to run()
if (running)
return;
final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
running = true;
for (;;) {
// "pollFirst" from unfinalized
Finalizer f;
synchronized (lock) {
f = unfinalized;
if (f == null) break;
unfinalized = f.next;
if (unfinalized != null)
unfinalized.prev = null;
f.next = f; // mark as finalized
}
f.runFinalizer(jla);
}}});
}
private static class FinalizerThread extends Thread {
private volatile boolean running;
FinalizerThread(ThreadGroup g) {
@ -203,7 +168,7 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
for (;;) {
try {
Finalizer f = (Finalizer)queue.remove();
f.deregisterAndRunFinalizer(jla);
f.runFinalizer(jla);
} catch (InterruptedException x) {
// ignore and continue
}

@ -27,9 +27,7 @@ package jdk.internal.misc;
import static java.lang.Thread.State.*;
import java.util.Map;
import java.util.HashMap;
import java.util.Properties;
import java.util.Collections;
public class VM {
@ -38,6 +36,8 @@ public class VM {
private static final int MODULE_SYSTEM_INITED = 2;
private static final int SYSTEM_LOADER_INITIALIZING = 3;
private static final int SYSTEM_BOOTED = 4;
private static final int SYSTEM_SHUTDOWN = 5;
// 0, 1, 2, ...
private static volatile int initLevel;
@ -52,7 +52,7 @@ public class VM {
*/
public static void initLevel(int value) {
synchronized (lock) {
if (value <= initLevel || value > SYSTEM_BOOTED)
if (value <= initLevel || value > SYSTEM_SHUTDOWN)
throw new InternalError("Bad level: " + value);
initLevel = value;
lock.notifyAll();
@ -94,6 +94,23 @@ public class VM {
return initLevel >= SYSTEM_BOOTED;
}
/**
* Set shutdown state. Shutdown completes when all registered shutdown
* hooks have been run.
*
* @see java.lang.Shutdown
*/
public static void shutdown() {
initLevel(SYSTEM_SHUTDOWN);
}
/**
* Returns {@code true} if the VM has been shutdown
*/
public static boolean isShutdown() {
return initLevel == SYSTEM_SHUTDOWN;
}
// A user-settable upper limit on the maximum amount of allocatable direct
// buffer memory. This value may be changed during VM initialization if
// "java" is launched with "-XX:MaxDirectMemorySize=<size>".

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
@ -35,17 +35,3 @@ Java_java_lang_Shutdown_halt0(JNIEnv *env, jclass ignored, jint code)
{
JVM_Halt(code);
}
JNIEXPORT void JNICALL
Java_java_lang_Shutdown_runAllFinalizers(JNIEnv *env, jclass ignored)
{
jclass cl;
jmethodID mid;
if ((cl = (*env)->FindClass(env, "java/lang/ref/Finalizer"))
&& (mid = (*env)->GetStaticMethodID(env, cl,
"runAllFinalizers", "()V"))) {
(*env)->CallStaticVoidMethod(env, cl, mid);
}
}

@ -80,8 +80,8 @@ import javax.lang.model.element.TypeElement;
* - handling of covariant overrides
* - handling of override of method found in multiple superinterfaces
* - convert type/method/field output to Java source like syntax, e.g.
* instead of java/lang/Runtime.runFinalizersOnExit(Z)V
* print void java.lang.Runtime.runFinalizersOnExit(boolean)
* instead of java/lang/Character.isJavaLetter(C)Z
* print void java.lang.Character.isJavaLetter(char)boolean
* - more example output in man page
* - more rigorous GNU style option parsing; use joptsimple?
*

@ -195,15 +195,14 @@ line separators) and is thus subject to quoting.
**EXAMPLE OUTPUT**
Given the following method declaration and annotation from the
`java.lang.Runtime` class,
`java.lang.Character` class,
@Deprecated(since="1.2",
forRemoval=true)
public static void runFinalizersOnExit(boolean value)
@Deprecated(since="1.1")
public static boolean isJavaLetter(char ch)
the following line will be emitted from **jdeprscan -Xprint-csv**:
METHOD,java/lang/Runtime,runFinalizersOnExit(Z)V,1.2,true
METHOD,java/lang/Character,isJavaLetter(C)Z,1.1,false
[RFC]: https://www.ietf.org/rfc/rfc4180.txt

@ -1,6 +1,6 @@
<!--
Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2016, 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
@ -134,30 +134,30 @@ of deprecated APIs listed is affected by the `--release` and the
The output is a report that lists program elements that use deprecated
APIs. Output is subject to change.
Consider the following declarations from Java SE 9:
Consider the following declarations:
// java.lang.Boolean
@Deprecated(since="9")
public Boolean(boolean value)
// java.lang.Runtime
// java.lang.Thread
@Deprecated(since="1.2", forRemoval=true)
public static void runFinalizersOnExit(boolean value)
@Deprecated(since="1.5", forRemoval=true)
public void destroy()
Running **jdeprscan** over a class that calls these methods will result
in output something like the following:
class Example uses method java/lang/Boolean.<init>(Z)V deprecated
class Example uses method java/lang/Runtime.runFinalizersOnExit(Z)V deprecated for removal
class Example uses method java/lang/Thread.destroy()V deprecated for removal
Running **jdeprscan** with the `--list` option will result in output
including something like the following:
...
@Deprecated(since="9") java.lang.Boolean(boolean)
@Deprecated(since="1.2", forRemoval=true) void java.lang.Runtime.runFinalizersOnExit(boolean)
@Deprecated(since="1.5", forRemoval=true) void java.lang.Thread.destroy()
...
**NOTES**

@ -12,7 +12,6 @@ java/lang/String::format(Ljava/lang/String;[Ljava/lang/Object;)
java/lang/String::format(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)
java/lang/System::exit(I)
java/lang/System::inheritedChannel()
java/lang/System::runFinalizersOnExit(Z)
java/util/AbstractSet::toString()
java/util/HashSet::toString()
java/lang/RuntimeException::setStackTrace([Ljava/lang/StackTraceElement;)

@ -49,12 +49,13 @@ public class Basic {
static Runtime rt = Runtime.getRuntime();
static PrintStream out = System.out;
// Expect that no finalizer is invoked at exit
@DataProvider(name = "testcase")
public Object[][] getTestCase() {
return new Object[][] {
{ "fallThrough", 0, "h1", "f1" },
{ "exit0", 0, "h1", "f1" },
{ "exit0NoHook", 0, "", "f1" },
{ "fallThrough", 0, "h1", "" },
{ "exit0", 0, "h1", "" },
{ "exit0NoHook", 0, "", "" },
{ "exit1", 1, "h1", "" },
{ "exit1NoHook", 1, "", "" },
{ "halt", 0, "", "" },
@ -112,19 +113,16 @@ public class Basic {
public static void fallThrough() throws Exception {
rt.addShutdownHook(new Hook("h1"));
Fin f = new Fin("f1");
rt.runFinalizersOnExit(true);
}
public static void exit0() throws Exception {
rt.addShutdownHook(new Hook("h1"));
Fin f = new Fin("f1");
rt.runFinalizersOnExit(true);
rt.exit(0);
}
public static void exit0NoHook() throws Exception {
Fin f = new Fin("f1");
rt.runFinalizersOnExit(true);
rt.exit(0);
}
@ -132,13 +130,11 @@ public class Basic {
public static void exit1() throws Exception {
rt.addShutdownHook(new Hook("h1"));
Fin f = new Fin("f1");
rt.runFinalizersOnExit(true);
rt.exit(1);
}
public static void exit1NoHook() throws Exception {
Fin f = new Fin("f1");
rt.runFinalizersOnExit(true);
rt.exit(1);
}
@ -146,13 +142,11 @@ public class Basic {
rt.addShutdownHook(new Hook("h1") {
public void go() { rt.halt(1); }});
Fin f = new Fin("f1") { public void go() { rt.halt(1); }};
rt.runFinalizersOnExit(true);
rt.halt(0);
}
public static void haltNoHook() throws Exception {
Fin f = new Fin("f1") { public void go() { rt.halt(1); }};
rt.runFinalizersOnExit(true);
rt.halt(0);
}
@ -160,7 +154,6 @@ public class Basic {
rt.addShutdownHook(new Hook("h1") {
public void go() { rt.halt(0); }});
Fin f = new Fin("f1");
rt.runFinalizersOnExit(true);
rt.exit(1);
}
@ -191,52 +184,9 @@ public class Basic {
rt.exit(1);
}
/* The following two methods are provided for manual testing only.
* Neither test is suitable for being run from within the harness.
*/
public static void awt() throws Exception {
final Frame f = new Frame();
final TextArea ta = new TextArea();
Fin fx = new Fin("f1");
rt.runFinalizersOnExit(true);
rt.addShutdownHook(new Hook("h1") {
public void go() {
ta.setText("Hooked!");
out.println("Hooked!");
try {
Thread.sleep(1000);
} catch (InterruptedException x) { }
ta.append("\nSleep 1");
out.println("Sleep 1");
try {
Thread.sleep(1000);
} catch (InterruptedException x) { }
ta.append("\nSleep 2");
out.println("Sleep 2");
}});
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
out.println("Closing...");
ta.setText("Closing...");
try {
Thread.sleep(1000);
} catch (InterruptedException x) { }
f.dispose();
rt.exit(42);
}});
ta.setText("Terminate me!");
f.add(ta);
f.pack();
f.show();
Thread.sleep(10000);
}
/* For INT, HUP, TERM */
public static void stall() throws Exception {
Fin f = new Fin("f1");
rt.runFinalizersOnExit(true);
rt.addShutdownHook(new Hook("h1"));
out.print("Type ^C now: ");
out.flush();

@ -1,36 +0,0 @@
/*
* Copyright (c) 1998, 2010, 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.
*/
/* @test
@bug 4119554
@summary runFinalizersOnExit(true) causes JIT to be unloaded and
crashes the VM. Interim fix for 1.2 beta4 -- don't unload
native libraries loaded by system classes.
@run main/othervm ExitFinalizersAndJIT
*/
public class ExitFinalizersAndJIT {
public static void main(String[] args) throws Exception {
System.runFinalizersOnExit(true);
}
}

@ -1,54 +0,0 @@
/*
* Copyright (c) 1998, 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.
*/
/* @test
@bug 4116016
@summary Ensure that finalizers are not invoked more than once when on-exit
finalization is enabled and a finalizer invokes System.exit after
System.exit has already been invoked
@build FinExit
@run shell FinExit.sh
*/
public class FinExit {
boolean finalized = false;
public void finalize() {
if (finalized) {
System.out.println("2");
} else {
finalized = true;
System.out.println("1");
System.exit(0);
}
}
public static void main(String[] args) throws Exception {
System.runFinalizersOnExit(true);
Object o = new FinExit();
System.exit(0);
}
}

@ -1,36 +0,0 @@
#! /bin/sh
#
# Copyright (c) 1998, 2010, 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.
#
#
# We only want the first character, Windows might add CRLF
x=`$TESTJAVA/bin/java ${TESTVMOPTS} -cp "$TESTCLASSES" FinExit | cut -c1`
echo $x
if [ "x$x" != "x1" ]; then
echo On-exit finalizer invoked twice
exit 1
else
exit 0
fi