8023168: Cleanup LogManager class initialization and LogManager/LoggerContext relationship
8021003: java/util/logging/Logger/getGlobal/TestGetGlobalConcurrent.java fails intermittently 8019945: test/java/util/logging/LogManagerInstanceTest.java failing intermittently This fix untangles the class initialization of Logger and LogManager, and also cleans up the relationship between LogManager, LoggerContext, and Logger, which were at the root cause of some intermittent test failures. Reviewed-by: mchung, martin, plevart
This commit is contained in:
parent
a4c7971bdb
commit
33dbc2d51c
@ -144,7 +144,7 @@ import sun.misc.SharedSecrets;
|
|||||||
|
|
||||||
public class LogManager {
|
public class LogManager {
|
||||||
// The global LogManager object
|
// The global LogManager object
|
||||||
private static LogManager manager;
|
private static final LogManager manager;
|
||||||
|
|
||||||
private Properties props = new Properties();
|
private Properties props = new Properties();
|
||||||
private final static Level defaultLevel = Level.INFO;
|
private final static Level defaultLevel = Level.INFO;
|
||||||
@ -156,8 +156,10 @@ public class LogManager {
|
|||||||
// LoggerContext for system loggers and user loggers
|
// LoggerContext for system loggers and user loggers
|
||||||
private final LoggerContext systemContext = new SystemLoggerContext();
|
private final LoggerContext systemContext = new SystemLoggerContext();
|
||||||
private final LoggerContext userContext = new LoggerContext();
|
private final LoggerContext userContext = new LoggerContext();
|
||||||
private Logger rootLogger;
|
// non final field - make it volatile to make sure that other threads
|
||||||
|
// will see the new value once ensureLogManagerInitialized() has finished
|
||||||
|
// executing.
|
||||||
|
private volatile Logger rootLogger;
|
||||||
// Have we done the primordial reading of the configuration file?
|
// Have we done the primordial reading of the configuration file?
|
||||||
// (Must be done after a suitable amount of java.lang.System
|
// (Must be done after a suitable amount of java.lang.System
|
||||||
// initialization has been done)
|
// initialization has been done)
|
||||||
@ -169,58 +171,35 @@ public class LogManager {
|
|||||||
private boolean deathImminent;
|
private boolean deathImminent;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
|
||||||
public Object run() {
|
@Override
|
||||||
String cname = null;
|
public LogManager run() {
|
||||||
try {
|
LogManager mgr = null;
|
||||||
cname = System.getProperty("java.util.logging.manager");
|
String cname = null;
|
||||||
if (cname != null) {
|
try {
|
||||||
try {
|
cname = System.getProperty("java.util.logging.manager");
|
||||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
|
if (cname != null) {
|
||||||
manager = (LogManager) clz.newInstance();
|
try {
|
||||||
} catch (ClassNotFoundException ex) {
|
Class<?> clz = ClassLoader.getSystemClassLoader()
|
||||||
Class<?> clz = Thread.currentThread().getContextClassLoader().loadClass(cname);
|
.loadClass(cname);
|
||||||
manager = (LogManager) clz.newInstance();
|
mgr = (LogManager) clz.newInstance();
|
||||||
}
|
} catch (ClassNotFoundException ex) {
|
||||||
|
Class<?> clz = Thread.currentThread()
|
||||||
|
.getContextClassLoader().loadClass(cname);
|
||||||
|
mgr = (LogManager) clz.newInstance();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
|
||||||
System.err.println("Could not load Logmanager \"" + cname + "\"");
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
}
|
||||||
if (manager == null) {
|
} catch (Exception ex) {
|
||||||
manager = new LogManager();
|
System.err.println("Could not load Logmanager \"" + cname + "\"");
|
||||||
}
|
ex.printStackTrace();
|
||||||
|
|
||||||
// Create and retain Logger for the root of the namespace.
|
|
||||||
manager.rootLogger = manager.new RootLogger();
|
|
||||||
// since by design the global manager's userContext and
|
|
||||||
// systemContext don't have their requiresDefaultLoggers
|
|
||||||
// flag set - we make sure to add the root logger to
|
|
||||||
// the global manager's default contexts here.
|
|
||||||
manager.addLogger(manager.rootLogger);
|
|
||||||
manager.systemContext.addLocalLogger(manager.rootLogger, false);
|
|
||||||
manager.userContext.addLocalLogger(manager.rootLogger, false);
|
|
||||||
|
|
||||||
// Adding the global Logger. Doing so in the Logger.<clinit>
|
|
||||||
// would deadlock with the LogManager.<clinit>.
|
|
||||||
// Do not call Logger.getGlobal() here as this might trigger
|
|
||||||
// the deadlock too.
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
final Logger global = Logger.global;
|
|
||||||
global.setLogManager(manager);
|
|
||||||
|
|
||||||
// Make sure the global logger will be registered in the
|
|
||||||
// global manager's default contexts.
|
|
||||||
manager.addLogger(global);
|
|
||||||
manager.systemContext.addLocalLogger(global, false);
|
|
||||||
manager.userContext.addLocalLogger(global, false);
|
|
||||||
|
|
||||||
// We don't call readConfiguration() here, as we may be running
|
|
||||||
// very early in the JVM startup sequence. Instead readConfiguration
|
|
||||||
// will be called lazily in getLogManager().
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
});
|
if (mgr == null) {
|
||||||
|
mgr = new LogManager();
|
||||||
|
}
|
||||||
|
return mgr;
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -235,6 +214,7 @@ public class LogManager {
|
|||||||
this.setContextClassLoader(null);
|
this.setContextClassLoader(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// This is to ensure the LogManager.<clinit> is completed
|
// This is to ensure the LogManager.<clinit> is completed
|
||||||
// before synchronized block. Otherwise deadlocks are possible.
|
// before synchronized block. Otherwise deadlocks are possible.
|
||||||
@ -270,13 +250,104 @@ public class LogManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lazy initialization: if this instance of manager is the global
|
||||||
|
* manager then this method will read the initial configuration and
|
||||||
|
* add the root logger and global logger by calling addLogger().
|
||||||
|
*
|
||||||
|
* Note that it is subtly different from what we do in LoggerContext.
|
||||||
|
* In LoggerContext we're patching up the logger context tree in order to add
|
||||||
|
* the root and global logger *to the context tree*.
|
||||||
|
*
|
||||||
|
* For this to work, addLogger() must have already have been called
|
||||||
|
* once on the LogManager instance for the default logger being
|
||||||
|
* added.
|
||||||
|
*
|
||||||
|
* This is why ensureLogManagerInitialized() needs to be called before
|
||||||
|
* any logger is added to any logger context.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private boolean initializedCalled = false;
|
||||||
|
private volatile boolean initializationDone = false;
|
||||||
|
final void ensureLogManagerInitialized() {
|
||||||
|
final LogManager owner = this;
|
||||||
|
if (initializationDone || owner != manager) {
|
||||||
|
// we don't want to do this twice, and we don't want to do
|
||||||
|
// this on private manager instances.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maybe another thread has called ensureLogManagerInitialized()
|
||||||
|
// before us and is still executing it. If so we will block until
|
||||||
|
// the log manager has finished initialized, then acquire the monitor,
|
||||||
|
// notice that initializationDone is now true and return.
|
||||||
|
// Otherwise - we have come here first! We will acquire the monitor,
|
||||||
|
// see that initializationDone is still false, and perform the
|
||||||
|
// initialization.
|
||||||
|
//
|
||||||
|
synchronized(this) {
|
||||||
|
// If initializedCalled is true it means that we're already in
|
||||||
|
// the process of initializing the LogManager in this thread.
|
||||||
|
// There has been a recursive call to ensureLogManagerInitialized().
|
||||||
|
final boolean isRecursiveInitialization = (initializedCalled == true);
|
||||||
|
|
||||||
|
assert initializedCalled || !initializationDone
|
||||||
|
: "Initialization can't be done if initialized has not been called!";
|
||||||
|
|
||||||
|
if (isRecursiveInitialization || initializationDone) {
|
||||||
|
// If isRecursiveInitialization is true it means that we're
|
||||||
|
// already in the process of initializing the LogManager in
|
||||||
|
// this thread. There has been a recursive call to
|
||||||
|
// ensureLogManagerInitialized(). We should not proceed as
|
||||||
|
// it would lead to infinite recursion.
|
||||||
|
//
|
||||||
|
// If initializationDone is true then it means the manager
|
||||||
|
// has finished initializing; just return: we're done.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Calling addLogger below will in turn call requiresDefaultLogger()
|
||||||
|
// which will call ensureLogManagerInitialized().
|
||||||
|
// We use initializedCalled to break the recursion.
|
||||||
|
initializedCalled = true;
|
||||||
|
try {
|
||||||
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
@Override
|
||||||
|
public Object run() {
|
||||||
|
assert rootLogger == null;
|
||||||
|
assert initializedCalled && !initializationDone;
|
||||||
|
|
||||||
|
// Read configuration.
|
||||||
|
owner.readPrimordialConfiguration();
|
||||||
|
|
||||||
|
// Create and retain Logger for the root of the namespace.
|
||||||
|
owner.rootLogger = owner.new RootLogger();
|
||||||
|
owner.addLogger(owner.rootLogger);
|
||||||
|
|
||||||
|
// Adding the global Logger.
|
||||||
|
// Do not call Logger.getGlobal() here as this might trigger
|
||||||
|
// subtle inter-dependency issues.
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
final Logger global = Logger.global;
|
||||||
|
|
||||||
|
// Make sure the global logger will be registered in the
|
||||||
|
// global manager
|
||||||
|
owner.addLogger(global);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
initializationDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the global LogManager object.
|
* Returns the global LogManager object.
|
||||||
* @return the global LogManager object
|
* @return the global LogManager object
|
||||||
*/
|
*/
|
||||||
public static LogManager getLogManager() {
|
public static LogManager getLogManager() {
|
||||||
if (manager != null) {
|
if (manager != null) {
|
||||||
manager.readPrimordialConfiguration();
|
manager.ensureLogManagerInitialized();
|
||||||
}
|
}
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
@ -295,6 +366,7 @@ public class LogManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
||||||
|
@Override
|
||||||
public Void run() throws Exception {
|
public Void run() throws Exception {
|
||||||
readConfiguration();
|
readConfiguration();
|
||||||
|
|
||||||
@ -304,8 +376,7 @@ public class LogManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// System.err.println("Can't read logging configuration:");
|
assert false : "Exception raised while reading logging configuration: " + ex;
|
||||||
// ex.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,7 +463,7 @@ public class LogManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoggerContext maps from AppContext
|
// LoggerContext maps from AppContext
|
||||||
private static WeakHashMap<Object, LoggerContext> contextsMap = null;
|
private WeakHashMap<Object, LoggerContext> contextsMap = null;
|
||||||
|
|
||||||
// Returns the LoggerContext for the user code (i.e. application or AppContext).
|
// Returns the LoggerContext for the user code (i.e. application or AppContext).
|
||||||
// Loggers are isolated from each AppContext.
|
// Loggers are isolated from each AppContext.
|
||||||
@ -414,10 +485,7 @@ public class LogManager {
|
|||||||
context = contextsMap.get(ecx);
|
context = contextsMap.get(ecx);
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
// Create a new LoggerContext for the applet.
|
// Create a new LoggerContext for the applet.
|
||||||
// The new logger context has its requiresDefaultLoggers
|
context = new LoggerContext();
|
||||||
// flag set to true - so that these loggers will be
|
|
||||||
// lazily added when the context is firt accessed.
|
|
||||||
context = new LoggerContext(true);
|
|
||||||
contextsMap.put(ecx, context);
|
contextsMap.put(ecx, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -427,9 +495,14 @@ public class LogManager {
|
|||||||
return context != null ? context : userContext;
|
return context != null ? context : userContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The system context.
|
||||||
|
final LoggerContext getSystemContext() {
|
||||||
|
return systemContext;
|
||||||
|
}
|
||||||
|
|
||||||
private List<LoggerContext> contexts() {
|
private List<LoggerContext> contexts() {
|
||||||
List<LoggerContext> cxs = new ArrayList<>();
|
List<LoggerContext> cxs = new ArrayList<>();
|
||||||
cxs.add(systemContext);
|
cxs.add(getSystemContext());
|
||||||
cxs.add(getUserContext());
|
cxs.add(getUserContext());
|
||||||
return cxs;
|
return cxs;
|
||||||
}
|
}
|
||||||
@ -450,7 +523,7 @@ public class LogManager {
|
|||||||
Logger result = getLogger(name);
|
Logger result = getLogger(name);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
// only allocate the new logger once
|
// only allocate the new logger once
|
||||||
Logger newLogger = new Logger(name, resourceBundleName, caller);
|
Logger newLogger = new Logger(name, resourceBundleName, caller, this);
|
||||||
do {
|
do {
|
||||||
if (addLogger(newLogger)) {
|
if (addLogger(newLogger)) {
|
||||||
// We successfully added the new Logger that we
|
// We successfully added the new Logger that we
|
||||||
@ -477,7 +550,7 @@ public class LogManager {
|
|||||||
|
|
||||||
Logger demandSystemLogger(String name, String resourceBundleName) {
|
Logger demandSystemLogger(String name, String resourceBundleName) {
|
||||||
// Add a system logger in the system context's namespace
|
// Add a system logger in the system context's namespace
|
||||||
final Logger sysLogger = systemContext.demandLogger(name, resourceBundleName);
|
final Logger sysLogger = getSystemContext().demandLogger(name, resourceBundleName);
|
||||||
|
|
||||||
// Add the system logger to the LogManager's namespace if not exist
|
// Add the system logger to the LogManager's namespace if not exist
|
||||||
// so that there is only one single logger of the given name.
|
// so that there is only one single logger of the given name.
|
||||||
@ -501,6 +574,7 @@ public class LogManager {
|
|||||||
// if logger already exists but handlers not set
|
// if logger already exists but handlers not set
|
||||||
final Logger l = logger;
|
final Logger l = logger;
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||||
|
@Override
|
||||||
public Void run() {
|
public Void run() {
|
||||||
for (Handler hdl : l.getHandlers()) {
|
for (Handler hdl : l.getHandlers()) {
|
||||||
sysLogger.addHandler(hdl);
|
sysLogger.addHandler(hdl);
|
||||||
@ -519,24 +593,52 @@ public class LogManager {
|
|||||||
// doesn't exist in the user context, it'll also be added to the user context.
|
// doesn't exist in the user context, it'll also be added to the user context.
|
||||||
// The user context is queried by the user code and all other loggers are
|
// The user context is queried by the user code and all other loggers are
|
||||||
// added in the user context.
|
// added in the user context.
|
||||||
static class LoggerContext {
|
class LoggerContext {
|
||||||
// Table of named Loggers that maps names to Loggers.
|
// Table of named Loggers that maps names to Loggers.
|
||||||
private final Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
|
private final Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
|
||||||
// Tree of named Loggers
|
// Tree of named Loggers
|
||||||
private final LogNode root;
|
private final LogNode root;
|
||||||
private final boolean requiresDefaultLoggers;
|
|
||||||
private LoggerContext() {
|
private LoggerContext() {
|
||||||
this(false);
|
|
||||||
}
|
|
||||||
private LoggerContext(boolean requiresDefaultLoggers) {
|
|
||||||
this.root = new LogNode(null, this);
|
this.root = new LogNode(null, this);
|
||||||
this.requiresDefaultLoggers = requiresDefaultLoggers;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Tells whether default loggers are required in this context.
|
||||||
|
// If true, the default loggers will be lazily added.
|
||||||
|
final boolean requiresDefaultLoggers() {
|
||||||
|
final boolean requiresDefaultLoggers = (getOwner() == manager);
|
||||||
|
if (requiresDefaultLoggers) {
|
||||||
|
getOwner().ensureLogManagerInitialized();
|
||||||
|
}
|
||||||
|
return requiresDefaultLoggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This context's LogManager.
|
||||||
|
final LogManager getOwner() {
|
||||||
|
return LogManager.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This context owner's root logger, which if not null, and if
|
||||||
|
// the context requires default loggers, will be added to the context
|
||||||
|
// logger's tree.
|
||||||
|
final Logger getRootLogger() {
|
||||||
|
return getOwner().rootLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The global logger, which if not null, and if
|
||||||
|
// the context requires default loggers, will be added to the context
|
||||||
|
// logger's tree.
|
||||||
|
final Logger getGlobalLogger() {
|
||||||
|
@SuppressWarnings("deprecated") // avoids initialization cycles.
|
||||||
|
final Logger global = Logger.global;
|
||||||
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger demandLogger(String name, String resourceBundleName) {
|
Logger demandLogger(String name, String resourceBundleName) {
|
||||||
// a LogManager subclass may have its own implementation to add and
|
// a LogManager subclass may have its own implementation to add and
|
||||||
// get a Logger. So delegate to the LogManager to do the work.
|
// get a Logger. So delegate to the LogManager to do the work.
|
||||||
return manager.demandLogger(name, resourceBundleName, null);
|
final LogManager owner = getOwner();
|
||||||
|
return owner.demandLogger(name, resourceBundleName, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -548,10 +650,10 @@ public class LogManager {
|
|||||||
// or getLoggerNames()
|
// or getLoggerNames()
|
||||||
//
|
//
|
||||||
private void ensureInitialized() {
|
private void ensureInitialized() {
|
||||||
if (requiresDefaultLoggers) {
|
if (requiresDefaultLoggers()) {
|
||||||
// Ensure that the root and global loggers are set.
|
// Ensure that the root and global loggers are set.
|
||||||
ensureDefaultLogger(manager.rootLogger);
|
ensureDefaultLogger(getRootLogger());
|
||||||
ensureDefaultLogger(Logger.global);
|
ensureDefaultLogger(getGlobalLogger());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,13 +682,13 @@ public class LogManager {
|
|||||||
// before adding 'logger'.
|
// before adding 'logger'.
|
||||||
//
|
//
|
||||||
private void ensureAllDefaultLoggers(Logger logger) {
|
private void ensureAllDefaultLoggers(Logger logger) {
|
||||||
if (requiresDefaultLoggers) {
|
if (requiresDefaultLoggers()) {
|
||||||
final String name = logger.getName();
|
final String name = logger.getName();
|
||||||
if (!name.isEmpty()) {
|
if (!name.isEmpty()) {
|
||||||
ensureDefaultLogger(manager.rootLogger);
|
ensureDefaultLogger(getRootLogger());
|
||||||
}
|
if (!Logger.GLOBAL_LOGGER_NAME.equals(name)) {
|
||||||
if (!Logger.GLOBAL_LOGGER_NAME.equals(name)) {
|
ensureDefaultLogger(getGlobalLogger());
|
||||||
ensureDefaultLogger(Logger.global);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,8 +700,8 @@ public class LogManager {
|
|||||||
// This check is simple sanity: we do not want that this
|
// This check is simple sanity: we do not want that this
|
||||||
// method be called for anything else than Logger.global
|
// method be called for anything else than Logger.global
|
||||||
// or owner.rootLogger.
|
// or owner.rootLogger.
|
||||||
if (!requiresDefaultLoggers || logger == null
|
if (!requiresDefaultLoggers() || logger == null
|
||||||
|| logger != Logger.global && logger != manager.rootLogger) {
|
|| logger != Logger.global && logger != LogManager.this.rootLogger) {
|
||||||
|
|
||||||
// the case where we have a non null logger which is neither
|
// the case where we have a non null logger which is neither
|
||||||
// Logger.global nor manager.rootLogger indicates a serious
|
// Logger.global nor manager.rootLogger indicates a serious
|
||||||
@ -625,7 +727,7 @@ public class LogManager {
|
|||||||
|
|
||||||
boolean addLocalLogger(Logger logger) {
|
boolean addLocalLogger(Logger logger) {
|
||||||
// no need to add default loggers if it's not required
|
// no need to add default loggers if it's not required
|
||||||
return addLocalLogger(logger, requiresDefaultLoggers);
|
return addLocalLogger(logger, requiresDefaultLoggers());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a logger to this context. This method will only set its level
|
// Add a logger to this context. This method will only set its level
|
||||||
@ -663,11 +765,13 @@ public class LogManager {
|
|||||||
|
|
||||||
// We're adding a new logger.
|
// We're adding a new logger.
|
||||||
// Note that we are creating a weak reference here.
|
// Note that we are creating a weak reference here.
|
||||||
ref = manager.new LoggerWeakRef(logger);
|
final LogManager owner = getOwner();
|
||||||
|
logger.setLogManager(owner);
|
||||||
|
ref = owner.new LoggerWeakRef(logger);
|
||||||
namedLoggers.put(name, ref);
|
namedLoggers.put(name, ref);
|
||||||
|
|
||||||
// Apply any initial level defined for the new logger.
|
// Apply any initial level defined for the new logger.
|
||||||
Level level = manager.getLevelProperty(name + ".level", null);
|
Level level = owner.getLevelProperty(name + ".level", null);
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
doSetLevel(logger, level);
|
doSetLevel(logger, level);
|
||||||
}
|
}
|
||||||
@ -719,10 +823,12 @@ public class LogManager {
|
|||||||
// If logger.getUseParentHandlers() returns 'true' and any of the logger's
|
// If logger.getUseParentHandlers() returns 'true' and any of the logger's
|
||||||
// parents have levels or handlers defined, make sure they are instantiated.
|
// parents have levels or handlers defined, make sure they are instantiated.
|
||||||
private void processParentHandlers(final Logger logger, final String name) {
|
private void processParentHandlers(final Logger logger, final String name) {
|
||||||
|
final LogManager owner = getOwner();
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||||
|
@Override
|
||||||
public Void run() {
|
public Void run() {
|
||||||
if (logger != manager.rootLogger) {
|
if (logger != owner.rootLogger) {
|
||||||
boolean useParent = manager.getBooleanProperty(name + ".useParentHandlers", true);
|
boolean useParent = owner.getBooleanProperty(name + ".useParentHandlers", true);
|
||||||
if (!useParent) {
|
if (!useParent) {
|
||||||
logger.setUseParentHandlers(false);
|
logger.setUseParentHandlers(false);
|
||||||
}
|
}
|
||||||
@ -738,8 +844,8 @@ public class LogManager {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
String pname = name.substring(0, ix2);
|
String pname = name.substring(0, ix2);
|
||||||
if (manager.getProperty(pname + ".level") != null ||
|
if (owner.getProperty(pname + ".level") != null ||
|
||||||
manager.getProperty(pname + ".handlers") != null) {
|
owner.getProperty(pname + ".handlers") != null) {
|
||||||
// This pname has a level/handlers definition.
|
// This pname has a level/handlers definition.
|
||||||
// Make sure it exists.
|
// Make sure it exists.
|
||||||
demandLogger(pname, null);
|
demandLogger(pname, null);
|
||||||
@ -779,16 +885,17 @@ public class LogManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SystemLoggerContext extends LoggerContext {
|
final class SystemLoggerContext extends LoggerContext {
|
||||||
// Add a system logger in the system context's namespace as well as
|
// Add a system logger in the system context's namespace as well as
|
||||||
// in the LogManager's namespace if not exist so that there is only
|
// in the LogManager's namespace if not exist so that there is only
|
||||||
// one single logger of the given name. System loggers are visible
|
// one single logger of the given name. System loggers are visible
|
||||||
// to applications unless a logger of the same name has been added.
|
// to applications unless a logger of the same name has been added.
|
||||||
|
@Override
|
||||||
Logger demandLogger(String name, String resourceBundleName) {
|
Logger demandLogger(String name, String resourceBundleName) {
|
||||||
Logger result = findLogger(name);
|
Logger result = findLogger(name);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
// only allocate the new system logger once
|
// only allocate the new system logger once
|
||||||
Logger newLogger = new Logger(name, resourceBundleName);
|
Logger newLogger = new Logger(name, resourceBundleName, null, getOwner());
|
||||||
do {
|
do {
|
||||||
if (addLocalLogger(newLogger)) {
|
if (addLocalLogger(newLogger)) {
|
||||||
// We successfully added the new Logger that we
|
// We successfully added the new Logger that we
|
||||||
@ -822,6 +929,7 @@ public class LogManager {
|
|||||||
final String handlersPropertyName)
|
final String handlersPropertyName)
|
||||||
{
|
{
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
@Override
|
||||||
public Object run() {
|
public Object run() {
|
||||||
String names[] = parseClassNames(handlersPropertyName);
|
String names[] = parseClassNames(handlersPropertyName);
|
||||||
for (int i = 0; i < names.length; i++) {
|
for (int i = 0; i < names.length; i++) {
|
||||||
@ -1014,6 +1122,7 @@ public class LogManager {
|
|||||||
// There is a security manager. Raise privilege before
|
// There is a security manager. Raise privilege before
|
||||||
// calling setLevel.
|
// calling setLevel.
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
@Override
|
||||||
public Object run() {
|
public Object run() {
|
||||||
logger.setLevel(level);
|
logger.setLevel(level);
|
||||||
return null;
|
return null;
|
||||||
@ -1032,6 +1141,7 @@ public class LogManager {
|
|||||||
// There is a security manager. Raise privilege before
|
// There is a security manager. Raise privilege before
|
||||||
// calling setParent.
|
// calling setParent.
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
@Override
|
||||||
public Object run() {
|
public Object run() {
|
||||||
logger.setParent(parent);
|
logger.setParent(parent);
|
||||||
return null;
|
return null;
|
||||||
@ -1129,14 +1239,9 @@ public class LogManager {
|
|||||||
f = new File(f, "logging.properties");
|
f = new File(f, "logging.properties");
|
||||||
fname = f.getCanonicalPath();
|
fname = f.getCanonicalPath();
|
||||||
}
|
}
|
||||||
InputStream in = new FileInputStream(fname);
|
try (final InputStream in = new FileInputStream(fname)) {
|
||||||
BufferedInputStream bin = new BufferedInputStream(in);
|
final BufferedInputStream bin = new BufferedInputStream(in);
|
||||||
try {
|
|
||||||
readConfiguration(bin);
|
readConfiguration(bin);
|
||||||
} finally {
|
|
||||||
if (in != null) {
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1201,7 +1306,7 @@ public class LogManager {
|
|||||||
}
|
}
|
||||||
hands = hands.trim();
|
hands = hands.trim();
|
||||||
int ix = 0;
|
int ix = 0;
|
||||||
Vector<String> result = new Vector<>();
|
final List<String> result = new ArrayList<>();
|
||||||
while (ix < hands.length()) {
|
while (ix < hands.length()) {
|
||||||
int end = ix;
|
int end = ix;
|
||||||
while (end < hands.length()) {
|
while (end < hands.length()) {
|
||||||
@ -1471,28 +1576,35 @@ public class LogManager {
|
|||||||
// We use a subclass of Logger for the root logger, so
|
// We use a subclass of Logger for the root logger, so
|
||||||
// that we only instantiate the global handlers when they
|
// that we only instantiate the global handlers when they
|
||||||
// are first needed.
|
// are first needed.
|
||||||
private class RootLogger extends Logger {
|
private final class RootLogger extends Logger {
|
||||||
private RootLogger() {
|
private RootLogger() {
|
||||||
super("", null);
|
// We do not call the protected Logger two args constructor here,
|
||||||
|
// to avoid calling LogManager.getLogManager() from within the
|
||||||
|
// RootLogger constructor.
|
||||||
|
super("", null, null, LogManager.this);
|
||||||
setLevel(defaultLevel);
|
setLevel(defaultLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void log(LogRecord record) {
|
public void log(LogRecord record) {
|
||||||
// Make sure that the global handlers have been instantiated.
|
// Make sure that the global handlers have been instantiated.
|
||||||
initializeGlobalHandlers();
|
initializeGlobalHandlers();
|
||||||
super.log(record);
|
super.log(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addHandler(Handler h) {
|
public void addHandler(Handler h) {
|
||||||
initializeGlobalHandlers();
|
initializeGlobalHandlers();
|
||||||
super.addHandler(h);
|
super.addHandler(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeHandler(Handler h) {
|
public void removeHandler(Handler h) {
|
||||||
initializeGlobalHandlers();
|
initializeGlobalHandlers();
|
||||||
super.removeHandler(h);
|
super.removeHandler(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Handler[] getHandlers() {
|
public Handler[] getHandlers() {
|
||||||
initializeGlobalHandlers();
|
initializeGlobalHandlers();
|
||||||
return super.getHandlers();
|
return super.getHandlers();
|
||||||
|
@ -245,14 +245,26 @@ public class Logger {
|
|||||||
// In order to finish the initialization of the global logger, we
|
// In order to finish the initialization of the global logger, we
|
||||||
// will therefore call LogManager.getLogManager() here.
|
// will therefore call LogManager.getLogManager() here.
|
||||||
//
|
//
|
||||||
// Care must be taken *not* to call Logger.getGlobal() in
|
// To prevent race conditions we also need to call
|
||||||
// LogManager static initializers in order to avoid such
|
// LogManager.getLogManager() unconditionally here.
|
||||||
// deadlocks.
|
// Indeed we cannot rely on the observed value of global.manager,
|
||||||
//
|
// because global.manager will become not null somewhere during
|
||||||
if (global != null && global.manager == null) {
|
// the initialization of LogManager.
|
||||||
// Complete initialization of the global Logger.
|
// If two threads are calling getGlobal() concurrently, one thread
|
||||||
global.manager = LogManager.getLogManager();
|
// will see global.manager null and call LogManager.getLogManager(),
|
||||||
}
|
// but the other thread could come in at a time when global.manager
|
||||||
|
// is already set although ensureLogManagerInitialized is not finished
|
||||||
|
// yet...
|
||||||
|
// Calling LogManager.getLogManager() unconditionally will fix that.
|
||||||
|
|
||||||
|
LogManager.getLogManager();
|
||||||
|
|
||||||
|
// Now the global LogManager should be initialized,
|
||||||
|
// and the global logger should have been added to
|
||||||
|
// it, unless we were called within the constructor of a LogManager
|
||||||
|
// subclass installed as LogManager, in which case global.manager
|
||||||
|
// would still be null, and global will be lazily initialized later on.
|
||||||
|
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,11 +310,11 @@ public class Logger {
|
|||||||
* no corresponding resource can be found.
|
* no corresponding resource can be found.
|
||||||
*/
|
*/
|
||||||
protected Logger(String name, String resourceBundleName) {
|
protected Logger(String name, String resourceBundleName) {
|
||||||
this(name, resourceBundleName, null);
|
this(name, resourceBundleName, null, LogManager.getLogManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger(String name, String resourceBundleName, Class<?> caller) {
|
Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager) {
|
||||||
this.manager = LogManager.getLogManager();
|
this.manager = manager;
|
||||||
setupResourceInfo(resourceBundleName, caller);
|
setupResourceInfo(resourceBundleName, caller);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
levelValue = Level.INFO.intValue();
|
levelValue = Level.INFO.intValue();
|
||||||
@ -332,8 +344,8 @@ public class Logger {
|
|||||||
levelValue = Level.INFO.intValue();
|
levelValue = Level.INFO.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is called from the LogManager.<clinit> to complete
|
// It is called from LoggerContext.addLocalLogger() when the logger
|
||||||
// initialization of the global Logger.
|
// is actually added to a LogManager.
|
||||||
void setLogManager(LogManager manager) {
|
void setLogManager(LogManager manager) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
}
|
}
|
||||||
@ -558,7 +570,7 @@ public class Logger {
|
|||||||
// cleanup some Loggers that have been GC'ed
|
// cleanup some Loggers that have been GC'ed
|
||||||
manager.drainLoggerRefQueueBounded();
|
manager.drainLoggerRefQueueBounded();
|
||||||
Logger result = new Logger(null, resourceBundleName,
|
Logger result = new Logger(null, resourceBundleName,
|
||||||
Reflection.getCallerClass());
|
Reflection.getCallerClass(), manager);
|
||||||
result.anonymous = true;
|
result.anonymous = true;
|
||||||
Logger root = manager.getLogger("");
|
Logger root = manager.getLogger("");
|
||||||
result.doSetParent(root);
|
result.doSetParent(root);
|
||||||
@ -1798,7 +1810,7 @@ public class Logger {
|
|||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
manager.checkPermission();
|
checkPermission();
|
||||||
doSetParent(parent);
|
doSetParent(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,12 @@ public class TestGetGlobal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
|
final String manager = System.getProperty("java.util.logging.manager", null);
|
||||||
|
|
||||||
|
final String description = "TestGetGlobal"
|
||||||
|
+ (System.getSecurityManager() == null ? " " :
|
||||||
|
" -Djava.security.manager ")
|
||||||
|
+ (manager == null ? "" : "-Djava.util.logging.manager=" + manager);
|
||||||
|
|
||||||
Logger.global.info(messages[0]); // at this point LogManager is not
|
Logger.global.info(messages[0]); // at this point LogManager is not
|
||||||
// initialized yet, so this message should not appear.
|
// initialized yet, so this message should not appear.
|
||||||
@ -67,7 +73,9 @@ public class TestGetGlobal {
|
|||||||
|
|
||||||
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, 1, messages.length));
|
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, 1, messages.length));
|
||||||
if (!testgetglobal.HandlerImpl.received.equals(expected)) {
|
if (!testgetglobal.HandlerImpl.received.equals(expected)) {
|
||||||
throw new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected);
|
System.err.println("Test case failed: " + description);
|
||||||
|
throw new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected
|
||||||
|
+ "\n\t"+description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,17 +22,18 @@
|
|||||||
*/
|
*/
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @bug 7184195
|
* @bug 7184195 8021003
|
||||||
* @summary checks that java.util.logging.Logger.getGlobal().info() logs without configuration
|
* @summary Test that the global logger can log with no configuration when accessed from multiple threads.
|
||||||
* @build TestGetGlobalConcurrent testgetglobal.HandlerImpl testgetglobal.LogManagerImpl1 testgetglobal.LogManagerImpl2 testgetglobal.LogManagerImpl3 testgetglobal.BadLogManagerImpl testgetglobal.DummyLogManagerImpl
|
* @build TestGetGlobalConcurrent testgetglobal.HandlerImpl testgetglobal.LogManagerImpl1 testgetglobal.LogManagerImpl2 testgetglobal.LogManagerImpl3 testgetglobal.BadLogManagerImpl testgetglobal.DummyLogManagerImpl
|
||||||
* @run main/othervm/timeout=10 TestGetGlobalConcurrent
|
* @run main/othervm/timeout=10 TestGetGlobalConcurrent
|
||||||
* @run main/othervm/timeout=10/policy=policy -Djava.security.manager TestGetGlobalConcurrent
|
* @run main/othervm/timeout=10/policy=policy -Djava.security.manager TestGetGlobalConcurrent
|
||||||
* @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl TestGetGlobalConcurrent
|
* @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobalConcurrent
|
||||||
* @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl TestGetGlobalConcurrent
|
* @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobalConcurrent
|
||||||
* @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalConcurrent
|
* @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalConcurrent
|
||||||
* @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalConcurrent
|
* @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalConcurrent
|
||||||
* @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalConcurrent
|
* @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalConcurrent
|
||||||
@ -69,7 +70,6 @@ public class TestGetGlobalConcurrent {
|
|||||||
// initialize the LogManager - and thus this message should appear.
|
// initialize the LogManager - and thus this message should appear.
|
||||||
Logger.global.info(messages[i+1]); // Now that the LogManager is
|
Logger.global.info(messages[i+1]); // Now that the LogManager is
|
||||||
// initialized, this message should appear too.
|
// initialized, this message should appear too.
|
||||||
|
|
||||||
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, i, i+2));
|
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, i, i+2));
|
||||||
if (!testgetglobal.HandlerImpl.received.containsAll(expected)) {
|
if (!testgetglobal.HandlerImpl.received.containsAll(expected)) {
|
||||||
fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected));
|
fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected));
|
||||||
@ -82,7 +82,6 @@ public class TestGetGlobalConcurrent {
|
|||||||
// initialize the LogManager - and thus this message should appear.
|
// initialize the LogManager - and thus this message should appear.
|
||||||
Logger.global.info(messages[i+1]); // Now that the LogManager is
|
Logger.global.info(messages[i+1]); // Now that the LogManager is
|
||||||
// initialized, this message should appear too.
|
// initialized, this message should appear too.
|
||||||
|
|
||||||
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, i, i+2));
|
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, i, i+2));
|
||||||
if (!testgetglobal.HandlerImpl.received.containsAll(expected)) {
|
if (!testgetglobal.HandlerImpl.received.containsAll(expected)) {
|
||||||
fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected));
|
fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected));
|
||||||
@ -96,7 +95,6 @@ public class TestGetGlobalConcurrent {
|
|||||||
// initialize the LogManager - and thus this message should appear.
|
// initialize the LogManager - and thus this message should appear.
|
||||||
Logger.global.info(messages[i+1]); // Now that the LogManager is
|
Logger.global.info(messages[i+1]); // Now that the LogManager is
|
||||||
// initialized, this message should appear too.
|
// initialized, this message should appear too.
|
||||||
|
|
||||||
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, i, i+2));
|
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, i, i+2));
|
||||||
if (!testgetglobal.HandlerImpl.received.containsAll(expected)) {
|
if (!testgetglobal.HandlerImpl.received.containsAll(expected)) {
|
||||||
fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected));
|
fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected));
|
||||||
@ -150,8 +148,17 @@ public class TestGetGlobalConcurrent {
|
|||||||
public void run() { test4(); }
|
public void run() { test4(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String description = "Unknown";
|
||||||
|
|
||||||
public static void main(String... args) throws Exception {
|
public static void main(String... args) throws Exception {
|
||||||
|
|
||||||
|
final String manager = System.getProperty("java.util.logging.manager", null);
|
||||||
|
|
||||||
|
description = "TestGetGlobalConcurrent"
|
||||||
|
+ (System.getSecurityManager() == null ? " " :
|
||||||
|
" -Djava.security.manager ")
|
||||||
|
+ (manager == null ? "" : "-Djava.util.logging.manager=" + manager);
|
||||||
|
|
||||||
final Thread t1 = new Thread(new WaitAndRun(new Run1()), "test1");
|
final Thread t1 = new Thread(new WaitAndRun(new Run1()), "test1");
|
||||||
final Thread t2 = new Thread(new WaitAndRun(new Run2()), "test2");
|
final Thread t2 = new Thread(new WaitAndRun(new Run2()), "test2");
|
||||||
final Thread t3 = new Thread(new WaitAndRun(new Run3()), "test3");
|
final Thread t3 = new Thread(new WaitAndRun(new Run3()), "test3");
|
||||||
@ -169,14 +176,13 @@ public class TestGetGlobalConcurrent {
|
|||||||
|
|
||||||
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, 1, 3));
|
final List<String> expected = Arrays.asList(Arrays.copyOfRange(messages, 1, 3));
|
||||||
if (!testgetglobal.HandlerImpl.received.containsAll(expected)) {
|
if (!testgetglobal.HandlerImpl.received.containsAll(expected)) {
|
||||||
throw new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected);
|
fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
t1.join(); t2.join(); t3.join(); t4.join();
|
t1.join(); t2.join(); t3.join(); t4.join();
|
||||||
|
|
||||||
if (failed != null) {
|
if (failed != null) {
|
||||||
throw new Error("Test failed.", failed);
|
throw new Error("Test failed: "+description, failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Test passed");
|
System.out.println("Test passed");
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
grant {
|
grant {
|
||||||
permission java.util.PropertyPermission "java.util.logging.config.file", "write";
|
permission java.util.PropertyPermission "java.util.logging.config.file", "write";
|
||||||
permission java.util.PropertyPermission "test.src", "read";
|
permission java.util.PropertyPermission "test.src", "read";
|
||||||
|
permission java.util.PropertyPermission "java.util.logging.manager", "read";
|
||||||
permission java.lang.RuntimePermission "setContextClassLoader";
|
permission java.lang.RuntimePermission "setContextClassLoader";
|
||||||
permission java.lang.RuntimePermission "shutdownHooks";
|
permission java.lang.RuntimePermission "shutdownHooks";
|
||||||
permission java.util.logging.LoggingPermission "control";
|
permission java.util.logging.LoggingPermission "control";
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
* @author ss45998
|
* @author ss45998
|
||||||
*
|
*
|
||||||
* @build ParentLoggersTest
|
* @build ParentLoggersTest
|
||||||
* @run main/othervm ParentLoggersTest
|
* @run main ParentLoggersTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -38,7 +38,7 @@ import sun.misc.SharedSecrets;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8017174 8010727
|
* @bug 8017174 8010727 8019945
|
||||||
* @summary NPE when using Logger.getAnonymousLogger or
|
* @summary NPE when using Logger.getAnonymousLogger or
|
||||||
* LogManager.getLogManager().getLogger
|
* LogManager.getLogManager().getLogger
|
||||||
*
|
*
|
||||||
@ -432,45 +432,36 @@ public class TestAppletLoggerContext {
|
|||||||
assertNull(manager.getLogger(""));
|
assertNull(manager.getLogger(""));
|
||||||
assertNull(manager.getLogger(""));
|
assertNull(manager.getLogger(""));
|
||||||
|
|
||||||
Bridge.changeContext();
|
for (int j = 0; j<3; j++) {
|
||||||
|
Bridge.changeContext();
|
||||||
|
|
||||||
// this is not a supported configuration:
|
// this is not a supported configuration:
|
||||||
// We are in an applet context with several log managers.
|
// We are in an applet context with several log managers.
|
||||||
// We however need to check our assumptions...
|
// We however need to check our assumptions...
|
||||||
|
|
||||||
// Applet context => root logger and global logger are not null.
|
// Applet context => root logger and global logger should also be null.
|
||||||
// root == LogManager.getLogManager().rootLogger
|
|
||||||
// global == Logger.global
|
|
||||||
|
|
||||||
Logger logger3 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
Logger expected = (System.getSecurityManager() == null ? global : null);
|
||||||
Logger logger3b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
Logger logger3 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||||
assertNotNull(logger3);
|
Logger logger3b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||||
assertNotNull(logger3b);
|
assertEquals(expected, logger3);
|
||||||
Logger expected = (System.getSecurityManager() != null
|
assertEquals(expected, logger3b);
|
||||||
? Logger.getGlobal()
|
Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||||
: global);
|
manager.addLogger(global2);
|
||||||
assertEquals(logger3, expected); // in applet context, we will not see
|
Logger logger4 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||||
// the LogManager's custom global logger added above...
|
Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||||
assertEquals(logger3b, expected); // in applet context, we will not see
|
assertNotNull(logger4);
|
||||||
// the LogManager's custom global logger added above...
|
assertNotNull(logger4b);
|
||||||
Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
|
expected = (System.getSecurityManager() == null ? global : global2);;
|
||||||
manager.addLogger(global2); // adding a global logger will not work in applet context
|
assertEquals(logger4, expected);
|
||||||
// we will always get back the global logger.
|
assertEquals(logger4b, expected);
|
||||||
// this could be considered as a bug...
|
|
||||||
Logger logger4 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
|
||||||
Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
|
||||||
assertNotNull(logger4);
|
|
||||||
assertNotNull(logger4b);
|
|
||||||
assertEquals(logger4, expected); // adding a global logger will not work in applet context
|
|
||||||
assertEquals(logger4b, expected); // adding a global logger will not work in applet context
|
|
||||||
|
|
||||||
Logger logger5 = manager.getLogger("");
|
Logger logger5 = manager.getLogger("");
|
||||||
Logger logger5b = manager.getLogger("");
|
Logger logger5b = manager.getLogger("");
|
||||||
Logger expectedRoot = (System.getSecurityManager() != null
|
Logger expectedRoot = null;
|
||||||
? LogManager.getLogManager().getLogger("")
|
assertEquals(logger5, expectedRoot);
|
||||||
: null);
|
assertEquals(logger5b, expectedRoot);
|
||||||
assertEquals(logger5, expectedRoot);
|
}
|
||||||
assertEquals(logger5b, expectedRoot);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -511,57 +502,53 @@ public class TestAppletLoggerContext {
|
|||||||
assertEquals(logger4, root);
|
assertEquals(logger4, root);
|
||||||
assertEquals(logger4b, root);
|
assertEquals(logger4b, root);
|
||||||
|
|
||||||
Bridge.changeContext();
|
for (int j = 0 ; j < 3 ; j++) {
|
||||||
|
Bridge.changeContext();
|
||||||
|
|
||||||
// this is not a supported configuration:
|
// this is not a supported configuration:
|
||||||
// We are in an applet context with several log managers.
|
// We are in an applet context with several log managers.
|
||||||
// We haowever need to check our assumptions...
|
// We however need to check our assumptions...
|
||||||
|
|
||||||
// Applet context => root logger and global logger are not null.
|
// Applet context => root logger and global logger should also be null.
|
||||||
// root == LogManager.getLogManager().rootLogger
|
|
||||||
// global == Logger.global
|
|
||||||
|
|
||||||
Logger logger5 = manager.getLogger("");
|
Logger logger5 = manager.getLogger("");
|
||||||
Logger logger5b = manager.getLogger("");
|
Logger logger5b = manager.getLogger("");
|
||||||
Logger expectedRoot = (System.getSecurityManager() != null
|
Logger expectedRoot = (System.getSecurityManager() == null ? root : null);
|
||||||
? LogManager.getLogManager().getLogger("")
|
assertEquals(logger5, expectedRoot);
|
||||||
: root);
|
assertEquals(logger5b, expectedRoot);
|
||||||
|
|
||||||
assertNotNull(logger5);
|
if (System.getSecurityManager() != null) {
|
||||||
assertNotNull(logger5b);
|
assertNull(manager.getLogger(Logger.GLOBAL_LOGGER_NAME));
|
||||||
assertEquals(logger5, expectedRoot);
|
} else {
|
||||||
assertEquals(logger5b, expectedRoot);
|
assertEquals(global, manager.getLogger(Logger.GLOBAL_LOGGER_NAME));
|
||||||
if (System.getSecurityManager() != null) {
|
}
|
||||||
assertNotEquals(logger5, root);
|
|
||||||
assertNotEquals(logger5b, root);
|
Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||||
|
manager.addLogger(global2);
|
||||||
|
Logger logger6 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||||
|
Logger logger6b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||||
|
Logger expectedGlobal = (System.getSecurityManager() == null ? global : global2);
|
||||||
|
|
||||||
|
assertNotNull(logger6);
|
||||||
|
assertNotNull(logger6b);
|
||||||
|
assertEquals(logger6, expectedGlobal);
|
||||||
|
assertEquals(logger6b, expectedGlobal);
|
||||||
|
if (System.getSecurityManager() != null) {
|
||||||
|
assertNull(manager.getLogger(""));
|
||||||
|
} else {
|
||||||
|
assertEquals(root, manager.getLogger(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger root2 = new Bridge.CustomLogger("");
|
||||||
|
manager.addLogger(root2);
|
||||||
|
expectedRoot = (System.getSecurityManager() == null ? root : root2);
|
||||||
|
Logger logger7 = manager.getLogger("");
|
||||||
|
Logger logger7b = manager.getLogger("");
|
||||||
|
assertNotNull(logger7);
|
||||||
|
assertNotNull(logger7b);
|
||||||
|
assertEquals(logger7, expectedRoot);
|
||||||
|
assertEquals(logger7b, expectedRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
|
|
||||||
manager.addLogger(global2); // adding a global logger will not work in applet context
|
|
||||||
// we will always get back the global logger.
|
|
||||||
// this could be considered as a bug...
|
|
||||||
Logger logger6 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
|
||||||
Logger logger6b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
|
||||||
Logger expectedGlobal = (System.getSecurityManager() != null
|
|
||||||
? Logger.getGlobal()
|
|
||||||
: global);
|
|
||||||
assertNotNull(logger6);
|
|
||||||
assertNotNull(logger6b);
|
|
||||||
assertEquals(logger6, expectedGlobal); // adding a global logger will not work in applet context
|
|
||||||
assertEquals(logger6b, expectedGlobal); // adding a global logger will not work in applet context
|
|
||||||
|
|
||||||
Logger root2 = new Bridge.CustomLogger("");
|
|
||||||
manager.addLogger(root2); // adding a root logger will not work in applet context
|
|
||||||
// we will always get back the default manager's root logger.
|
|
||||||
// this could be considered as a bug...
|
|
||||||
Logger logger7 = manager.getLogger("");
|
|
||||||
Logger logger7b = manager.getLogger("");
|
|
||||||
assertNotNull(logger7);
|
|
||||||
assertNotNull(logger7b);
|
|
||||||
assertEquals(logger7, expectedRoot); // adding a global logger will not work in applet context
|
|
||||||
assertEquals(logger7b, expectedRoot); // adding a global logger will not work in applet context
|
|
||||||
assertNotEquals(logger7, root2);
|
|
||||||
assertNotEquals(logger7b, root2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user