src/share/classes/java/util/logging/Logger.java
Print this page
rev 7022 : 8013380: Removal of stack walk to find resource bundle breaks Glassfish startup
Summary: Use caller's classloader to load resource as an alternative to thread context classloader and system classloader
Reviewed-by: duke
*** 216,225 ****
--- 216,226 ----
// references from children to parents.
private volatile Logger parent; // our nearest parent.
private ArrayList<LogManager.LoggerWeakRef> kids; // WeakReferences to loggers that have us as parent
private volatile Level levelObject;
private volatile int levelValue; // current effective level value
+ private WeakReference<ClassLoader> callersClassLoaderRef;
/**
* GLOBAL_LOGGER_NAME is a name for the global logger.
*
* @since 1.6
*** 275,292 ****
* messages for this logger. May be null if none
* of the messages require localization.
* @throws MissingResourceException if the resourceBundleName is non-null and
* no corresponding resource can be found.
*/
protected Logger(String name, String resourceBundleName) {
this.manager = LogManager.getLogManager();
if (resourceBundleName != null) {
// MissingResourceException or IllegalArgumentException can
// be thrown by setupResourceInfo(). Since this is the Logger
// constructor, the resourceBundleName field is null so
// IllegalArgumentException cannot happen here.
! setupResourceInfo(resourceBundleName);
}
this.name = name;
levelValue = Level.INFO.intValue();
}
--- 276,301 ----
* messages for this logger. May be null if none
* of the messages require localization.
* @throws MissingResourceException if the resourceBundleName is non-null and
* no corresponding resource can be found.
*/
+ @CallerSensitive
protected Logger(String name, String resourceBundleName) {
+ this(name, resourceBundleName,
+ Reflection.getCallerClass().getClassLoader());
+ }
+
+ Logger(String name, String resourceBundleName,
+ ClassLoader callersClassLoader) {
this.manager = LogManager.getLogManager();
+ this.callersClassLoaderRef = new WeakReference(callersClassLoader);
if (resourceBundleName != null) {
// MissingResourceException or IllegalArgumentException can
// be thrown by setupResourceInfo(). Since this is the Logger
// constructor, the resourceBundleName field is null so
// IllegalArgumentException cannot happen here.
! setupResourceInfo(resourceBundleName, callersClassLoader);
}
this.name = name;
levelValue = Level.INFO.intValue();
}
*** 341,351 ****
if (sm != null && !SystemLoggerHelper.disableCallerCheck) {
if (caller.getClassLoader() == null) {
return manager.demandSystemLogger(name, resourceBundleName);
}
}
! return manager.demandLogger(name, resourceBundleName);
}
/**
* Find or create a logger for a named subsystem. If a logger has
* already been created with the given name it is returned. Otherwise
--- 350,361 ----
if (sm != null && !SystemLoggerHelper.disableCallerCheck) {
if (caller.getClassLoader() == null) {
return manager.demandSystemLogger(name, resourceBundleName);
}
}
! return manager.demandLogger(name, resourceBundleName,
! caller.getClassLoader());
}
/**
* Find or create a logger for a named subsystem. If a logger has
* already been created with the given name it is returned. Otherwise
*** 434,448 ****
// Synchronization is not required here. All synchronization for
// adding a new Logger object is handled by LogManager.addLogger().
@CallerSensitive
public static Logger getLogger(String name, String resourceBundleName) {
! Logger result = demandLogger(name, resourceBundleName, Reflection.getCallerClass());
// MissingResourceException or IllegalArgumentException can be
// thrown by setupResourceInfo().
! result.setupResourceInfo(resourceBundleName);
return result;
}
// package-private
// Add a platform logger to the system context.
--- 444,459 ----
// Synchronization is not required here. All synchronization for
// adding a new Logger object is handled by LogManager.addLogger().
@CallerSensitive
public static Logger getLogger(String name, String resourceBundleName) {
! Class callerClass = Reflection.getCallerClass();
! Logger result = demandLogger(name, resourceBundleName, callerClass);
// MissingResourceException or IllegalArgumentException can be
// thrown by setupResourceInfo().
! result.setupResourceInfo(resourceBundleName, callerClass.getClassLoader());
return result;
}
// package-private
// Add a platform logger to the system context.
*** 525,535 ****
* bundle inherited from its parent.
*
* @return localization bundle (may be null)
*/
public ResourceBundle getResourceBundle() {
! return findResourceBundle(getResourceBundleName());
}
/**
* Retrieve the localization resource bundle name for this
* logger. Note that if the result is null, then the Logger
--- 536,548 ----
* bundle inherited from its parent.
*
* @return localization bundle (may be null)
*/
public ResourceBundle getResourceBundle() {
! return findResourceBundle(getResourceBundleName(),
! (callersClassLoaderRef != null ? callersClassLoaderRef.get() :
! null));
}
/**
* Retrieve the localization resource bundle name for this
* logger. Note that if the result is null, then the Logger
*** 607,617 ****
private void doLog(LogRecord lr) {
lr.setLoggerName(name);
String ebname = getEffectiveResourceBundleName();
if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) {
lr.setResourceBundleName(ebname);
! lr.setResourceBundle(findResourceBundle(ebname));
}
log(lr);
}
--- 620,633 ----
private void doLog(LogRecord lr) {
lr.setLoggerName(name);
String ebname = getEffectiveResourceBundleName();
if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) {
lr.setResourceBundleName(ebname);
! lr.setResourceBundle(findResourceBundle(ebname,
! (callersClassLoaderRef != null
! ? callersClassLoaderRef.get()
! : null)));
}
log(lr);
}
*** 934,944 ****
// resource bundle and then call "void log(LogRecord)".
private void doLog(LogRecord lr, String rbname) {
lr.setLoggerName(name);
if (rbname != null) {
lr.setResourceBundleName(rbname);
! lr.setResourceBundle(findResourceBundle(rbname));
}
log(lr);
}
/**
--- 950,963 ----
// resource bundle and then call "void log(LogRecord)".
private void doLog(LogRecord lr, String rbname) {
lr.setLoggerName(name);
if (rbname != null) {
lr.setResourceBundleName(rbname);
! lr.setResourceBundle(findResourceBundle(rbname,
! (callersClassLoaderRef != null
! ? callersClassLoaderRef.get()
! : null)));
}
log(lr);
}
/**
*** 1609,1619 ****
* there is no suitable previous cached value.
*
* @param name the ResourceBundle to locate
* @return ResourceBundle specified by name or null if not found
*/
! private synchronized ResourceBundle findResourceBundle(String name) {
// Return a null bundle for a null name.
if (name == null) {
return null;
}
--- 1628,1639 ----
* there is no suitable previous cached value.
*
* @param name the ResourceBundle to locate
* @return ResourceBundle specified by name or null if not found
*/
! private synchronized ResourceBundle findResourceBundle(String name,
! ClassLoader callersClassLoader) {
// Return a null bundle for a null name.
if (name == null) {
return null;
}
*** 1642,1662 ****
catalog = ResourceBundle.getBundle(name, currentLocale, cl);
catalogName = name;
catalogLocale = currentLocale;
return catalog;
} catch (MissingResourceException ex) {
return null;
}
}
// Private utility method to initialize our one entry
// resource bundle name cache.
// Note: for consistency reasons, we are careful to check
// that a suitable ResourceBundle exists before setting the
// resourceBundleName field.
// Synchronized to prevent races in setting the field.
! private synchronized void setupResourceInfo(String name) {
if (name == null) {
return;
}
if (resourceBundleName != null) {
--- 1662,1699 ----
catalog = ResourceBundle.getBundle(name, currentLocale, cl);
catalogName = name;
catalogLocale = currentLocale;
return catalog;
} catch (MissingResourceException ex) {
+ // Woops. We can't find the ResourceBundle in the default
+ // ClassLoader. Drop through.
+ }
+
+ // Try with the caller's ClassLoader
+ if (callersClassLoader == null) {
return null;
}
+
+ try {
+ catalog = ResourceBundle.getBundle(name, currentLocale,
+ callersClassLoader);
+ catalogName = name;
+ catalogLocale = currentLocale;
+ return catalog;
+ } catch (MissingResourceException ex) {
+ return null; // no luck
+ }
}
// Private utility method to initialize our one entry
// resource bundle name cache.
// Note: for consistency reasons, we are careful to check
// that a suitable ResourceBundle exists before setting the
// resourceBundleName field.
// Synchronized to prevent races in setting the field.
! private synchronized void setupResourceInfo(String name,
! ClassLoader callersClassLoader) {
if (name == null) {
return;
}
if (resourceBundleName != null) {
*** 1670,1682 ****
// cannot change ResourceBundles once they are set
throw new IllegalArgumentException(
resourceBundleName + " != " + name);
}
! if (findResourceBundle(name) == null) {
// We've failed to find an expected ResourceBundle.
! throw new MissingResourceException("Can't find " + name + " bundle", name, "");
}
resourceBundleName = name;
}
/**
--- 1707,1720 ----
// cannot change ResourceBundles once they are set
throw new IllegalArgumentException(
resourceBundleName + " != " + name);
}
! if (findResourceBundle(name, callersClassLoader) == null) {
// We've failed to find an expected ResourceBundle.
! throw new MissingResourceException("Can't find " + name + " bundle",
! name, "");
}
resourceBundleName = name;
}
/**