--- old/src/share/classes/java/util/logging/Logger.java 2013-09-04 21:12:15.000000000 +0200 +++ new/src/share/classes/java/util/logging/Logger.java 2013-09-04 21:12:15.000000000 +0200 @@ -244,15 +244,37 @@ // // In order to finish the initialization of the global logger, we // will therefore call LogManager.getLogManager() here. - // - // Care must be taken *not* to call Logger.getGlobal() in - // LogManager static initializers in order to avoid such - // deadlocks. - // if (global != null && global.manager == null) { // Complete initialization of the global Logger. + // In practice this should never happen - unless getGlobal() is called + // from within a subclass of LogManager being installed as + // global LogManager - in which case LogManager.getLogManager() will + // return null anyway... global.manager = LogManager.getLogManager(); } + + // To prevent race conditions we also need to ensure that + // the global logger was added the log manager. + // We do that here. It will either initialize the manager + // or wait for it to be initialized. + // Indeed global.manager will become not null somewhen during + // the initalization of LogManager. + // If two threads are calling getGlobal() concurrently, one thread + // will see global.manager null and call LogMnager.getLogManager(), + // but the other thread could come in at a time when global.manager + // is already set although ensureLogManagerInitialized is not finished + // yet... + // Calling manager.ensureLogManagerInitialized() should fix that. + if (global.manager != null) { + global.manager.ensureLogManagerInitialized(); + } + + // Now the global LogManager should be initialized, + // and the global logger should have been added to + // it, unless we where 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; } @@ -298,11 +320,11 @@ * no corresponding resource can be found. */ protected Logger(String name, String resourceBundleName) { - this(name, resourceBundleName, null); + this(name, resourceBundleName, null, LogManager.getLogManager()); } - Logger(String name, String resourceBundleName, Class caller) { - this.manager = LogManager.getLogManager(); + Logger(String name, String resourceBundleName, Class caller, LogManager manager) { + this.manager = manager; setupResourceInfo(resourceBundleName, caller); this.name = name; levelValue = Level.INFO.intValue(); @@ -558,7 +580,7 @@ // cleanup some Loggers that have been GC'ed manager.drainLoggerRefQueueBounded(); Logger result = new Logger(null, resourceBundleName, - Reflection.getCallerClass()); + Reflection.getCallerClass(), manager); result.anonymous = true; Logger root = manager.getLogger(""); result.doSetParent(root); @@ -1798,7 +1820,7 @@ if (parent == null) { throw new NullPointerException(); } - manager.checkPermission(); + checkPermission(); doSetParent(parent); }