8002070: Remove the stack search for a resource bundle for Logger to use
The fragile, vulnerable, stack crawling has been eliminated from findResourceBundle(String) Reviewed-by: mchung, alanb
This commit is contained in:
parent
0bcb468549
commit
709f67b8f9
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -26,10 +26,13 @@
|
|||||||
|
|
||||||
package java.util.logging;
|
package java.util.logging;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
import java.security.*;
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,7 +107,7 @@ import java.util.function.Supplier;
|
|||||||
* unnecessary message construction. For example, if the developer wants to
|
* unnecessary message construction. For example, if the developer wants to
|
||||||
* log system health status for diagnosis, with the String-accepting version,
|
* log system health status for diagnosis, with the String-accepting version,
|
||||||
* the code would look like:
|
* the code would look like:
|
||||||
<code><pre>
|
<pre><code>
|
||||||
|
|
||||||
class DiagnosisMessages {
|
class DiagnosisMessages {
|
||||||
static String systemHealthStatus() {
|
static String systemHealthStatus() {
|
||||||
@ -114,26 +117,20 @@ import java.util.function.Supplier;
|
|||||||
}
|
}
|
||||||
...
|
...
|
||||||
logger.log(Level.FINER, DiagnosisMessages.systemHealthStatus());
|
logger.log(Level.FINER, DiagnosisMessages.systemHealthStatus());
|
||||||
</pre></code>
|
</code></pre>
|
||||||
* With the above code, the health status is collected unnecessarily even when
|
* With the above code, the health status is collected unnecessarily even when
|
||||||
* the log level FINER is disabled. With the Supplier-accepting version as
|
* the log level FINER is disabled. With the Supplier-accepting version as
|
||||||
* below, the status will only be collected when the log level FINER is
|
* below, the status will only be collected when the log level FINER is
|
||||||
* enabled.
|
* enabled.
|
||||||
<code><pre>
|
<pre><code>
|
||||||
|
|
||||||
logger.log(Level.FINER, DiagnosisMessages::systemHealthStatus);
|
logger.log(Level.FINER, DiagnosisMessages::systemHealthStatus);
|
||||||
</pre></code>
|
</code></pre>
|
||||||
* <p>
|
* <p>
|
||||||
* When mapping ResourceBundle names to ResourceBundles, the Logger
|
* When mapping ResourceBundle names to ResourceBundles, the Logger
|
||||||
* will first try to use the Thread's ContextClassLoader. If that
|
* will first try to use the Thread's ContextClassLoader. If that
|
||||||
* is null it will try the SystemClassLoader instead. As a temporary
|
* is null it will try the
|
||||||
* transition feature in the initial implementation, if the Logger is
|
* {@linkplain java.lang.ClassLoader#getSystemClassLoader() system ClassLoader} instead.
|
||||||
* unable to locate a ResourceBundle from the ContextClassLoader or
|
|
||||||
* SystemClassLoader the Logger will also search up the class stack
|
|
||||||
* and use successive calling ClassLoaders to try to locate a ResourceBundle.
|
|
||||||
* (This call stack search is to allow containers to transition to
|
|
||||||
* using ContextClassLoaders and is likely to be removed in future
|
|
||||||
* versions.)
|
|
||||||
* <p>
|
* <p>
|
||||||
* Formatting (including localization) is the responsibility of
|
* Formatting (including localization) is the responsibility of
|
||||||
* the output Handler, which will typically call a Formatter.
|
* the output Handler, which will typically call a Formatter.
|
||||||
@ -1541,12 +1538,16 @@ public class Logger {
|
|||||||
return useParentHandlers;
|
return useParentHandlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private utility method to map a resource bundle name to an
|
/**
|
||||||
// actual resource bundle, using a simple one-entry cache.
|
* Private utility method to map a resource bundle name to an
|
||||||
// Returns null for a null name.
|
* actual resource bundle, using a simple one-entry cache.
|
||||||
// May also return null if we can't find the resource bundle and
|
* Returns null for a null name.
|
||||||
// there is no suitable previous cached value.
|
* May also return null if we can't find the resource bundle and
|
||||||
|
* 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) {
|
private synchronized ResourceBundle findResourceBundle(String name) {
|
||||||
// Return a null bundle for a null name.
|
// Return a null bundle for a null name.
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
@ -1556,13 +1557,13 @@ public class Logger {
|
|||||||
Locale currentLocale = Locale.getDefault();
|
Locale currentLocale = Locale.getDefault();
|
||||||
|
|
||||||
// Normally we should hit on our simple one entry cache.
|
// Normally we should hit on our simple one entry cache.
|
||||||
if (catalog != null && currentLocale == catalogLocale
|
if (catalog != null && currentLocale.equals(catalogLocale)
|
||||||
&& name == catalogName) {
|
&& name.equals(catalogName)) {
|
||||||
return catalog;
|
return catalog;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the thread's context ClassLoader. If there isn't one,
|
// Use the thread's context ClassLoader. If there isn't one, use the
|
||||||
// use the SystemClassloader.
|
// {@linkplain java.lang.ClassLoader#getSystemClassLoader() system ClassLoader}.
|
||||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
cl = ClassLoader.getSystemClassLoader();
|
cl = ClassLoader.getSystemClassLoader();
|
||||||
@ -1573,45 +1574,8 @@ public class Logger {
|
|||||||
catalogLocale = currentLocale;
|
catalogLocale = currentLocale;
|
||||||
return catalog;
|
return catalog;
|
||||||
} catch (MissingResourceException ex) {
|
} catch (MissingResourceException ex) {
|
||||||
// Woops. We can't find the ResourceBundle in the default
|
return null;
|
||||||
// ClassLoader. Drop through.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Fall back to searching up the call stack and trying each
|
|
||||||
// calling ClassLoader.
|
|
||||||
for (int ix = 0; ; ix++) {
|
|
||||||
Class clz = sun.reflect.Reflection.getCallerClass(ix);
|
|
||||||
if (clz == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ClassLoader cl2 = clz.getClassLoader();
|
|
||||||
if (cl2 == null) {
|
|
||||||
cl2 = ClassLoader.getSystemClassLoader();
|
|
||||||
}
|
|
||||||
if (cl == cl2) {
|
|
||||||
// We've already checked this classloader.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cl = cl2;
|
|
||||||
try {
|
|
||||||
catalog = ResourceBundle.getBundle(name, currentLocale, cl);
|
|
||||||
catalogName = name;
|
|
||||||
catalogLocale = currentLocale;
|
|
||||||
return catalog;
|
|
||||||
} catch (MissingResourceException ex) {
|
|
||||||
// Ok, this one didn't work either.
|
|
||||||
// Drop through, and try the next one.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.equals(catalogName)) {
|
|
||||||
// Return the previous cached value for that name.
|
|
||||||
// This may be null.
|
|
||||||
return catalog;
|
|
||||||
}
|
|
||||||
// Sorry, we're out of luck.
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private utility method to initialize our one entry
|
// Private utility method to initialize our one entry
|
||||||
@ -1638,8 +1602,7 @@ public class Logger {
|
|||||||
resourceBundleName + " != " + name);
|
resourceBundleName + " != " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceBundle rb = findResourceBundle(name);
|
if (findResourceBundle(name) == null) {
|
||||||
if (rb == null) {
|
|
||||||
// We've failed to find an expected ResourceBundle.
|
// We've failed to find an expected ResourceBundle.
|
||||||
throw new MissingResourceException("Can't find " + name + " bundle", name, "");
|
throw new MissingResourceException("Can't find " + name + " bundle", name, "");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,13 +23,14 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 7045594
|
* @bug 7045594 8002070
|
||||||
* @summary ResourceBundle setting race in Logger.getLogger(name, rbName)
|
* @summary ResourceBundle setting race in Logger.getLogger(name, rbName)
|
||||||
* @author Daniel D. Daugherty
|
* @author Daniel D. Daugherty
|
||||||
* @build RacingThreadsTest LoggerResourceBundleRace
|
* @build RacingThreadsTest LoggerResourceBundleRace
|
||||||
* @run main LoggerResourceBundleRace
|
* @run main/othervm LoggerResourceBundleRace
|
||||||
|
*
|
||||||
|
* (In samevm mode, the bundle classes don't end up in the classpath.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ListResourceBundle;
|
import java.util.ListResourceBundle;
|
||||||
import java.util.MissingResourceException;
|
import java.util.MissingResourceException;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user