--- old/src/java.logging/share/classes/java/util/logging/LogManager.java 2014-11-05 17:21:18.000000000 +0100
+++ new/src/java.logging/share/classes/java/util/logging/LogManager.java 2014-11-05 17:21:18.000000000 +0100
@@ -31,6 +31,7 @@
import java.security.*;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
+import java.util.concurrent.CopyOnWriteArrayList;
import sun.misc.JavaAWTAccess;
import sun.misc.SharedSecrets;
@@ -100,6 +101,19 @@
* Note that these Handlers may be created lazily, when they are
* first used.
*
+ *
A property "<logger>.handlers.ensureCloseOnReset". This defines a
+ * a boolean value. If "<logger>.handlers" is not defined or is empty,
+ * this property is ignored. Otherwise it defaults to {@code true}. When the
+ * value is {@code true}, the handlers associated with the logger are guaranteed
+ * to be closed on {@linkplain reset} and shutdown. This can be turned off
+ * by explicitly setting "<logger>.handlers.ensureCloseOnReset=false" in
+ * the configuration. Note that turning this property off causes the risk of
+ * introducing a resource leak, as the logger may get garbage collected before
+ * {@code reset()} is called, thus preventing its handlers from being closed
+ * on {@code reset()}. In that case it is the responsibility of the application
+ * to ensure that the handlers are closed before the logger is garbage
+ * collected.
+ *
*
A property "<logger>.useParentHandlers". This defines a boolean
* value. By default every logger calls its parent in addition to
* handling the logging message itself, this often result in messages
@@ -169,6 +183,33 @@
// True if JVM death is imminent and the exit hook has been called.
private boolean deathImminent;
+ // This list contains the loggers for which some handlers have been
+ // explicitly configured in the configuration file.
+ // It prevents these loggers from being arbitrarily garbage collected.
+ private static final class CloseOnReset {
+ private final Logger logger;
+ private CloseOnReset(Logger ref) {
+ this.logger = Objects.requireNonNull(ref);
+ }
+ @Override
+ public boolean equals(Object other) {
+ return (other instanceof CloseOnReset) && ((CloseOnReset)other).logger == logger;
+ }
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(logger);
+ }
+ public Logger get() {
+ return logger;
+ }
+ public static CloseOnReset create(Logger logger) {
+ return new CloseOnReset(logger);
+ }
+ }
+ private final CopyOnWriteArrayList closeOnResetLoggers =
+ new CopyOnWriteArrayList<>();
+
+
private final Map