227
228 /**
229 * Return global logger object with the name Logger.GLOBAL_LOGGER_NAME.
230 *
231 * @return global logger object
232 * @since 1.7
233 */
234 public static final Logger getGlobal() {
235 // In order to break a cyclic dependence between the LogManager
236 // and Logger static initializers causing deadlocks, the global
237 // logger is created with a special constructor that does not
238 // initialize its log manager.
239 //
240 // If an application calls Logger.getGlobal() before any logger
241 // has been initialized, it is therefore possible that the
242 // LogManager class has not been initialized yet, and therefore
243 // Logger.global.manager will be null.
244 //
245 // In order to finish the initialization of the global logger, we
246 // will therefore call LogManager.getLogManager() here.
247 //
248 // Care must be taken *not* to call Logger.getGlobal() in
249 // LogManager static initializers in order to avoid such
250 // deadlocks.
251 //
252 if (global != null && global.manager == null) {
253 // Complete initialization of the global Logger.
254 global.manager = LogManager.getLogManager();
255 }
256 return global;
257 }
258
259 /**
260 * The "global" Logger object is provided as a convenience to developers
261 * who are making casual use of the Logging package. Developers
262 * who are making serious use of the logging package (for example
263 * in products) should create and use their own Logger objects,
264 * with appropriate names, so that logging can be controlled on a
265 * suitable per-Logger granularity. Developers also need to keep a
266 * strong reference to their Logger objects to prevent them from
267 * being garbage collected.
268 * <p>
269 * @deprecated Initialization of this field is prone to deadlocks.
270 * The field must be initialized by the Logger class initialization
271 * which may cause deadlocks with the LogManager class initialization.
272 * In such cases two class initialization wait for each other to complete.
273 * The preferred way to get the global logger object is via the call
274 * <code>Logger.getGlobal()</code>.
275 * For compatibility with old JDK versions where the
281 public static final Logger global = new Logger(GLOBAL_LOGGER_NAME);
282
283 /**
284 * Protected method to construct a logger for a named subsystem.
285 * <p>
286 * The logger will be initially configured with a null Level
287 * and with useParentHandlers set to true.
288 *
289 * @param name A name for the logger. This should
290 * be a dot-separated name and should normally
291 * be based on the package name or class name
292 * of the subsystem, such as java.net
293 * or javax.swing. It may be null for anonymous Loggers.
294 * @param resourceBundleName name of ResourceBundle to be used for localizing
295 * messages for this logger. May be null if none
296 * of the messages require localization.
297 * @throws MissingResourceException if the resourceBundleName is non-null and
298 * no corresponding resource can be found.
299 */
300 protected Logger(String name, String resourceBundleName) {
301 this(name, resourceBundleName, null);
302 }
303
304 Logger(String name, String resourceBundleName, Class<?> caller) {
305 this.manager = LogManager.getLogManager();
306 setupResourceInfo(resourceBundleName, caller);
307 this.name = name;
308 levelValue = Level.INFO.intValue();
309 }
310
311 private void setCallersClassLoaderRef(Class<?> caller) {
312 ClassLoader callersClassLoader = ((caller != null)
313 ? caller.getClassLoader()
314 : null);
315 if (callersClassLoader != null) {
316 this.callersClassLoaderRef = new WeakReference(callersClassLoader);
317 }
318 }
319
320 private ClassLoader getCallersClassLoader() {
321 return (callersClassLoaderRef != null)
322 ? callersClassLoaderRef.get()
323 : null;
324 }
325
541 * to have the root logger ("") as its parent. This means that
542 * by default it inherits its effective level and handlers
543 * from the root logger.
544 * <p>
545 * @param resourceBundleName name of ResourceBundle to be used for localizing
546 * messages for this logger.
547 * May be null if none of the messages require localization.
548 * @return a newly created private Logger
549 * @throws MissingResourceException if the resourceBundleName is non-null and
550 * no corresponding resource can be found.
551 */
552
553 // Synchronization is not required here. All synchronization for
554 // adding a new anonymous Logger object is handled by doSetParent().
555 @CallerSensitive
556 public static Logger getAnonymousLogger(String resourceBundleName) {
557 LogManager manager = LogManager.getLogManager();
558 // cleanup some Loggers that have been GC'ed
559 manager.drainLoggerRefQueueBounded();
560 Logger result = new Logger(null, resourceBundleName,
561 Reflection.getCallerClass());
562 result.anonymous = true;
563 Logger root = manager.getLogger("");
564 result.doSetParent(root);
565 return result;
566 }
567
568 /**
569 * Retrieve the localization resource bundle for this
570 * logger for the current default locale. Note that if
571 * the result is null, then the Logger will use a resource
572 * bundle inherited from its parent.
573 *
574 * @return localization bundle (may be null)
575 */
576 public ResourceBundle getResourceBundle() {
577 return findResourceBundle(getResourceBundleName(), true);
578 }
579
580 /**
581 * Retrieve the localization resource bundle name for this
1781 // would synchronize on treeLock (in fact, there is no way for external
1782 // callers to so synchronize). Therefore, we have made parent volatile
1783 // instead.
1784 return parent;
1785 }
1786
1787 /**
1788 * Set the parent for this Logger. This method is used by
1789 * the LogManager to update a Logger when the namespace changes.
1790 * <p>
1791 * It should not be called from application code.
1792 * <p>
1793 * @param parent the new parent logger
1794 * @exception SecurityException if a security manager exists and if
1795 * the caller does not have LoggingPermission("control").
1796 */
1797 public void setParent(Logger parent) {
1798 if (parent == null) {
1799 throw new NullPointerException();
1800 }
1801 manager.checkPermission();
1802 doSetParent(parent);
1803 }
1804
1805 // Private method to do the work for parenting a child
1806 // Logger onto a parent logger.
1807 private void doSetParent(Logger newParent) {
1808
1809 // System.err.println("doSetParent \"" + getName() + "\" \""
1810 // + newParent.getName() + "\"");
1811
1812 synchronized (treeLock) {
1813
1814 // Remove ourself from any previous parent.
1815 LogManager.LoggerWeakRef ref = null;
1816 if (parent != null) {
1817 // assert parent.kids != null;
1818 for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) {
1819 ref = iter.next();
1820 Logger kid = ref.get();
1821 if (kid == this) {
|
227
228 /**
229 * Return global logger object with the name Logger.GLOBAL_LOGGER_NAME.
230 *
231 * @return global logger object
232 * @since 1.7
233 */
234 public static final Logger getGlobal() {
235 // In order to break a cyclic dependence between the LogManager
236 // and Logger static initializers causing deadlocks, the global
237 // logger is created with a special constructor that does not
238 // initialize its log manager.
239 //
240 // If an application calls Logger.getGlobal() before any logger
241 // has been initialized, it is therefore possible that the
242 // LogManager class has not been initialized yet, and therefore
243 // Logger.global.manager will be null.
244 //
245 // In order to finish the initialization of the global logger, we
246 // will therefore call LogManager.getLogManager() here.
247 if (global != null && global.manager == null) {
248 // Complete initialization of the global Logger.
249 // In practice this should never happen - unless getGlobal() is called
250 // from within a subclass of LogManager being installed as
251 // global LogManager - in which case LogManager.getLogManager() will
252 // return null anyway...
253 global.manager = LogManager.getLogManager();
254 }
255
256 // To prevent race conditions we also need to ensure that
257 // the global logger was added the log manager.
258 // We do that here. It will either initialize the manager
259 // or wait for it to be initialized.
260 // Indeed global.manager will become not null somewhen during
261 // the initalization of LogManager.
262 // If two threads are calling getGlobal() concurrently, one thread
263 // will see global.manager null and call LogMnager.getLogManager(),
264 // but the other thread could come in at a time when global.manager
265 // is already set although ensureLogManagerInitialized is not finished
266 // yet...
267 // Calling manager.ensureLogManagerInitialized() should fix that.
268 if (global.manager != null) {
269 global.manager.ensureLogManagerInitialized();
270 }
271
272 // Now the global LogManager should be initialized,
273 // and the global logger should have been added to
274 // it, unless we where called within the constructor of a LogManager
275 // subclass installed as LogManager, in which case global.manager
276 // would still be null, and global will be lazily initialized later on.
277
278 return global;
279 }
280
281 /**
282 * The "global" Logger object is provided as a convenience to developers
283 * who are making casual use of the Logging package. Developers
284 * who are making serious use of the logging package (for example
285 * in products) should create and use their own Logger objects,
286 * with appropriate names, so that logging can be controlled on a
287 * suitable per-Logger granularity. Developers also need to keep a
288 * strong reference to their Logger objects to prevent them from
289 * being garbage collected.
290 * <p>
291 * @deprecated Initialization of this field is prone to deadlocks.
292 * The field must be initialized by the Logger class initialization
293 * which may cause deadlocks with the LogManager class initialization.
294 * In such cases two class initialization wait for each other to complete.
295 * The preferred way to get the global logger object is via the call
296 * <code>Logger.getGlobal()</code>.
297 * For compatibility with old JDK versions where the
303 public static final Logger global = new Logger(GLOBAL_LOGGER_NAME);
304
305 /**
306 * Protected method to construct a logger for a named subsystem.
307 * <p>
308 * The logger will be initially configured with a null Level
309 * and with useParentHandlers set to true.
310 *
311 * @param name A name for the logger. This should
312 * be a dot-separated name and should normally
313 * be based on the package name or class name
314 * of the subsystem, such as java.net
315 * or javax.swing. It may be null for anonymous Loggers.
316 * @param resourceBundleName name of ResourceBundle to be used for localizing
317 * messages for this logger. May be null if none
318 * of the messages require localization.
319 * @throws MissingResourceException if the resourceBundleName is non-null and
320 * no corresponding resource can be found.
321 */
322 protected Logger(String name, String resourceBundleName) {
323 this(name, resourceBundleName, null, LogManager.getLogManager());
324 }
325
326 Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager) {
327 this.manager = manager;
328 setupResourceInfo(resourceBundleName, caller);
329 this.name = name;
330 levelValue = Level.INFO.intValue();
331 }
332
333 private void setCallersClassLoaderRef(Class<?> caller) {
334 ClassLoader callersClassLoader = ((caller != null)
335 ? caller.getClassLoader()
336 : null);
337 if (callersClassLoader != null) {
338 this.callersClassLoaderRef = new WeakReference(callersClassLoader);
339 }
340 }
341
342 private ClassLoader getCallersClassLoader() {
343 return (callersClassLoaderRef != null)
344 ? callersClassLoaderRef.get()
345 : null;
346 }
347
563 * to have the root logger ("") as its parent. This means that
564 * by default it inherits its effective level and handlers
565 * from the root logger.
566 * <p>
567 * @param resourceBundleName name of ResourceBundle to be used for localizing
568 * messages for this logger.
569 * May be null if none of the messages require localization.
570 * @return a newly created private Logger
571 * @throws MissingResourceException if the resourceBundleName is non-null and
572 * no corresponding resource can be found.
573 */
574
575 // Synchronization is not required here. All synchronization for
576 // adding a new anonymous Logger object is handled by doSetParent().
577 @CallerSensitive
578 public static Logger getAnonymousLogger(String resourceBundleName) {
579 LogManager manager = LogManager.getLogManager();
580 // cleanup some Loggers that have been GC'ed
581 manager.drainLoggerRefQueueBounded();
582 Logger result = new Logger(null, resourceBundleName,
583 Reflection.getCallerClass(), manager);
584 result.anonymous = true;
585 Logger root = manager.getLogger("");
586 result.doSetParent(root);
587 return result;
588 }
589
590 /**
591 * Retrieve the localization resource bundle for this
592 * logger for the current default locale. Note that if
593 * the result is null, then the Logger will use a resource
594 * bundle inherited from its parent.
595 *
596 * @return localization bundle (may be null)
597 */
598 public ResourceBundle getResourceBundle() {
599 return findResourceBundle(getResourceBundleName(), true);
600 }
601
602 /**
603 * Retrieve the localization resource bundle name for this
1803 // would synchronize on treeLock (in fact, there is no way for external
1804 // callers to so synchronize). Therefore, we have made parent volatile
1805 // instead.
1806 return parent;
1807 }
1808
1809 /**
1810 * Set the parent for this Logger. This method is used by
1811 * the LogManager to update a Logger when the namespace changes.
1812 * <p>
1813 * It should not be called from application code.
1814 * <p>
1815 * @param parent the new parent logger
1816 * @exception SecurityException if a security manager exists and if
1817 * the caller does not have LoggingPermission("control").
1818 */
1819 public void setParent(Logger parent) {
1820 if (parent == null) {
1821 throw new NullPointerException();
1822 }
1823 checkPermission();
1824 doSetParent(parent);
1825 }
1826
1827 // Private method to do the work for parenting a child
1828 // Logger onto a parent logger.
1829 private void doSetParent(Logger newParent) {
1830
1831 // System.err.println("doSetParent \"" + getName() + "\" \""
1832 // + newParent.getName() + "\"");
1833
1834 synchronized (treeLock) {
1835
1836 // Remove ourself from any previous parent.
1837 LogManager.LoggerWeakRef ref = null;
1838 if (parent != null) {
1839 // assert parent.kids != null;
1840 for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) {
1841 ref = iter.next();
1842 Logger kid = ref.get();
1843 if (kid == this) {
|