< 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 >