< prev index next >

src/java.logging/share/classes/java/util/logging/LogManager.java

Print this page

        

*** 29,38 **** --- 29,39 ---- import java.io.*; import java.util.*; 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; /** * There is a single global LogManager object that is used to
*** 167,176 **** --- 168,204 ---- // This gets set to false in readConfiguration private boolean initializedGlobalHandlers = true; // 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 + // explicitely configured in the configuration file. + // It prevents these loggers from being arbitrarily garbage collected. + private static final class PersistentLogger { + private final Logger logger; + private PersistentLogger(Logger ref) { + this.logger = Objects.requireNonNull(ref); + } + @Override + public boolean equals(Object other) { + return (other instanceof PersistentLogger) && ((PersistentLogger)other).logger == logger; + } + @Override + public int hashCode() { + return System.identityHashCode(logger); + } + public Logger get() { + return logger; + } + public static PersistentLogger create(Logger logger) { + return new PersistentLogger(logger); + } + } + private final CopyOnWriteArrayList<PersistentLogger> persistentLoggers = + new CopyOnWriteArrayList<>(); + + private final Map<Object, Runnable> listeners = Collections.synchronizedMap(new IdentityHashMap<>()); static { manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
*** 202,212 **** } }); } - // This private class is used as a shutdown hook. // It does a "reset" to close all open handlers. private class Cleaner extends Thread { private Cleaner() { --- 230,239 ----
*** 873,906 **** { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { String names[] = parseClassNames(handlersPropertyName); ! for (String word : names) { try { ! Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word); Handler hdl = (Handler) clz.newInstance(); // Check if there is a property defining the // this handler's level. ! String levs = getProperty(word + ".level"); if (levs != null) { Level l = Level.findLevel(levs); if (l != null) { hdl.setLevel(l); } else { // Probably a bad level. Drop through. ! System.err.println("Can't set level for " + word); } } // Add this Handler to the logger logger.addHandler(hdl); } catch (Exception ex) { ! System.err.println("Can't load log handler \"" + word + "\""); System.err.println("" + ex); ex.printStackTrace(); } } return null; } }); } --- 900,940 ---- { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { String names[] = parseClassNames(handlersPropertyName); ! int count = 0; ! for (String type : names) { try { ! Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(type); Handler hdl = (Handler) clz.newInstance(); // Check if there is a property defining the // this handler's level. ! String levs = getProperty(type + ".level"); if (levs != null) { Level l = Level.findLevel(levs); if (l != null) { hdl.setLevel(l); } else { // Probably a bad level. Drop through. ! System.err.println("Can't set level for " + type); } } // Add this Handler to the logger logger.addHandler(hdl); + if (++count == 1) { + // add this logger to the persitentLoggers list. + persistentLoggers.addIfAbsent( + PersistentLogger.create(logger)); + } } catch (Exception ex) { ! System.err.println("Can't load log handler \"" + type + "\""); System.err.println("" + ex); ex.printStackTrace(); } } + return null; } }); }
*** 1231,1242 **** --- 1265,1283 ---- * the caller does not have LoggingPermission("control"). */ public void reset() throws SecurityException { checkPermission(); + List<PersistentLogger> persistent; synchronized (this) { props = new Properties(); + // make sure we keep the loggers persistent until reset is done. + // Those are the loggers for which we previously created a + // handler from the configuration, and we need to prevent them + // from being gc'ed until those handlers are closed. + persistent = new ArrayList<>(persistentLoggers); + persistentLoggers.clear(); // Since we are doing a reset we no longer want to initialize // the global handlers, if they haven't been initialized yet. initializedGlobalHandlers = true; } for (LoggerContext cx : contexts()) {
*** 1247,1256 **** --- 1288,1298 ---- if (logger != null) { resetLogger(logger); } } } + persistent.clear(); } // Private method to reset an individual target logger. private void resetLogger(Logger logger) { // Close all the Logger's handlers.
< prev index next >