# HG changeset patch # User mchung # Date 1519416656 28800 # Node ID a6c4b85163c18d9182f32494e4ac983adf865c94 # Parent 4f11514fe783b9cf4da6a48487ac1223f5ea9bd1 8198249: Remove deprecated Runtime::runFinalizersOnExit and System::runFinalizersOnExit Reviewed-by: dholmes, alanb, smarks diff -r 4f11514fe783 -r a6c4b85163c1 make/mapfiles/libjava/mapfile-vers --- a/make/mapfiles/libjava/mapfile-vers Fri Feb 23 14:26:29 2018 -0500 +++ b/make/mapfiles/libjava/mapfile-vers Fri Feb 23 12:10:56 2018 -0800 @@ -143,7 +143,6 @@ 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; diff -r 4f11514fe783 -r a6c4b85163c1 src/hotspot/share/classfile/vmSymbols.hpp --- a/src/hotspot/share/classfile/vmSymbols.hpp Fri Feb 23 14:26:29 2018 -0500 +++ b/src/hotspot/share/classfile/vmSymbols.hpp Fri Feb 23 12:10:56 2018 -0800 @@ -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") \ diff -r 4f11514fe783 -r a6c4b85163c1 src/hotspot/share/memory/universe.cpp --- a/src/hotspot/share/memory/universe.cpp Fri Feb 23 14:26:29 2018 -0500 +++ b/src/hotspot/share/memory/universe.cpp Fri Feb 23 12:10:56 2018 -0800 @@ -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 @@ #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 diff -r 4f11514fe783 -r a6c4b85163c1 src/hotspot/share/memory/universe.hpp --- a/src/hotspot/share/memory/universe.hpp Fri Feb 23 14:26:29 2018 -0500 +++ b/src/hotspot/share/memory/universe.hpp Fri Feb 23 12:10:56 2018 -0800 @@ -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 @@ 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 diff -r 4f11514fe783 -r a6c4b85163c1 src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp Fri Feb 23 14:26:29 2018 -0500 +++ b/src/hotspot/share/runtime/thread.cpp Fri Feb 23 12:10:56 2018 -0800 @@ -4202,10 +4202,9 @@ // 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 @@ // + 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()) diff -r 4f11514fe783 -r a6c4b85163c1 src/java.base/share/classes/java/lang/Runtime.java --- a/src/java.base/share/classes/java/lang/Runtime.java Fri Feb 23 14:26:29 2018 -0500 +++ b/src/java.base/share/classes/java/lang/Runtime.java Fri Feb 23 12:10:56 2018 -0800 @@ -79,18 +79,14 @@ * serves as a status code; by convention, a nonzero status code indicates * abnormal termination. * - *
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}. + *
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}. * - *
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 + *
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. * *
The {@link System#exit(int) System.exit} method is the @@ -109,7 +105,6 @@ * @see java.lang.SecurityManager#checkExit(int) * @see #addShutdownHook * @see #removeShutdownHook - * @see #runFinalizersOnExit * @see #halt(int) */ public void exit(int status) { @@ -142,10 +137,9 @@ * 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. * *
Once the shutdown sequence has begun it can be stopped only by * invoking the {@link #halt halt} method, which forcibly @@ -255,10 +249,9 @@ * *
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 @@ -286,46 +279,6 @@ } /** - * 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. - * - *
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. * *
This is a convenience method. An invocation of the form diff -r 4f11514fe783 -r a6c4b85163c1 src/java.base/share/classes/java/lang/Shutdown.java --- a/src/java.base/share/classes/java/lang/Shutdown.java Fri Feb 23 14:26:29 2018 -0500 +++ b/src/java.base/share/classes/java/lang/Shutdown.java Fri Feb 23 12:10:56 2018 -0800 @@ -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 @@ /* 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 @@ * 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 @@ } } - /* 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 @@ 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 @@ 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 @@ * 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(); } } diff -r 4f11514fe783 -r a6c4b85163c1 src/java.base/share/classes/java/lang/System.java --- a/src/java.base/share/classes/java/lang/System.java Fri Feb 23 14:26:29 2018 -0500 +++ b/src/java.base/share/classes/java/lang/System.java Fri Feb 23 12:10:56 2018 -0800 @@ -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 @@ -1766,38 +1766,6 @@ } /** - * 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. - * - *
If there is a security manager,
- * its checkExit
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 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)
- @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.
*
diff -r 4f11514fe783 -r a6c4b85163c1 src/java.base/share/classes/java/lang/doc-files/threadPrimitiveDeprecation.html
--- a/src/java.base/share/classes/java/lang/doc-files/threadPrimitiveDeprecation.html Fri Feb 23 14:26:29 2018 -0500
+++ b/src/java.base/share/classes/java/lang/doc-files/threadPrimitiveDeprecation.html Fri Feb 23 12:10:56 2018 -0800
@@ -1,6 +1,6 @@