webappClassLoader.clearThreadLocalDebugClear=To simplify the process of tracing memory leaks, the key has been forcibly removed.
webappClassLoader.clearThreadLocalClear=To prevent a memory leak, the ThreadLocal has been forcibly removed.
webappClassLoader.clearThreadLocalFail=Failed to clear ThreadLocal references for web application [{0}]
+webappClassLoader.clearThreadLocal.badKey=Unable to determine string representation of key of type [{0}]
+webappClassLoader.clearThreadLocal.badValue=Unable to determine string representation of value of type [{0}]
+webappClassLoader.clearThreadLocal.unknown=Unknown
webappClassLoader.stopThreadFail=Failed to terminate thread named [{0}] for web application [{1}]
webappClassLoader.stopTimerThreadFail=Failed to terminate TimerThread named [{0}] for web application [{1}]
webappClassLoader.validationErrorJarPath=Unable to validate JAR entry with name {0}
args[0] = contextName;
if (key != null) {
args[1] = key.getClass().getCanonicalName();
- args[2] = key.toString();
+ try {
+ args[2] = key.toString();
+ } catch (Exception e) {
+ log.error(sm.getString(
+ "webappClassLoader.clearThreadLocal.badKey",
+ args[1]), e);
+ args[2] = sm.getString(
+ "webappClassLoader.clearThreadLocal.unknown");
+ }
}
if (value != null) {
args[3] = value.getClass().getCanonicalName();
- args[4] = value.toString();
+ try {
+ args[4] = value.toString();
+ } catch (Exception e) {
+ log.error(sm.getString(
+ "webappClassLoader.clearThreadLocal.badValue",
+ args[3]), e);
+ args[4] = sm.getString(
+ "webappClassLoader.clearThreadLocal.unknown");
+ }
}
if (value == null) {
if (log.isDebugEnabled()) {
<code>AsyncContext.dispatch()</code> once the asynchronous request has
timed out. (markt)
</fix>
+ <add>
+ Make memory leak prevention code that clears ThreadLocal instances more
+ robust against objects with toString() methods that throw exceptions.
+ (markt)
+ </add>
</changelog>
</subsection>
<subsection name="Coyote">