You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by kk...@apache.org on 2012/07/02 14:04:12 UTC
svn commit: r1356198 - in /tomcat/tc6.0.x/trunk: STATUS.txt
java/org/apache/catalina/loader/WebappClassLoader.java
webapps/docs/changelog.xml
Author: kkolinko
Date: Mon Jul 2 12:04:11 2012
New Revision: 1356198
URL: http://svn.apache.org/viewvc?rev=1356198&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52850
Extend memory leak prevention and detection code to
work with IBM as well as Oracle JVMs. Based on a patch provided by Rohit Kelapure.
Modified:
tomcat/tc6.0.x/trunk/STATUS.txt
tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java
tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
Modified: tomcat/tc6.0.x/trunk/STATUS.txt
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=1356198&r1=1356197&r2=1356198&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/STATUS.txt (original)
+++ tomcat/tc6.0.x/trunk/STATUS.txt Mon Jul 2 12:04:11 2012
@@ -127,13 +127,6 @@ PATCHES PROPOSED TO BACKPORT:
+1: kkolinko
-1:
-* Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52850
- Extend memory leak prevention and detection code to
- work with IBM as well as Oracle JVMs. Based on patch provided by Rohit Kelapure.
- https://issues.apache.org/bugzilla/attachment.cgi?id=28893
- +1: kkolinko, schultz, markt
- -1:
-
* Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=53047
Allow database realms configured with an all roles mode that is authentication
only to not have to define a role table
Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java?rev=1356198&r1=1356197&r2=1356198&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/loader/WebappClassLoader.java Mon Jul 2 12:04:11 2012
@@ -2177,8 +2177,9 @@ public class WebappClassLoader
}
// TimerThread can be stopped safely so treat separately
- if (thread.getClass().getName().equals(
- "java.util.TimerThread") &&
+ // "java.util.TimerThread" in Sun/Oracle JDK
+ // "java.util.Timer$TimerImpl" in Apache Harmony and in IBM JDK
+ if (thread.getClass().getName().startsWith("java.util.Timer") &&
clearReferencesStopTimerThreads) {
clearReferencesStopTimerThread(thread);
continue;
@@ -2201,13 +2202,29 @@ public class WebappClassLoader
// If the thread has been started via an executor, try
// shutting down the executor
try {
- Field targetField =
- thread.getClass().getDeclaredField("target");
- targetField.setAccessible(true);
- Object target = targetField.get(thread);
-
+ // Runnable wrapped by Thread
+ // "target" in Sun/Oracle JDK
+ // "runnable" in IBM JDK
+ // "action" in Apache Harmony
+ Object target = null;
+ for (String fieldName : new String[] { "target",
+ "runnable", "action" }) {
+ try {
+ Field targetField = thread.getClass()
+ .getDeclaredField(fieldName);
+ targetField.setAccessible(true);
+ target = targetField.get(thread);
+ break;
+ } catch (NoSuchFieldException nfe) {
+ continue;
+ }
+ }
+
+ // "java.util.concurrent" code is in public domain,
+ // so all implementations are similar
if (target != null &&
- target.getClass().getCanonicalName().equals(
+ target.getClass().getCanonicalName() != null
+ && target.getClass().getCanonicalName().equals(
"java.util.concurrent.ThreadPoolExecutor.Worker")) {
Field executorField =
target.getClass().getDeclaredField("this$0");
@@ -2276,37 +2293,46 @@ public class WebappClassLoader
private void clearReferencesStopTimerThread(Thread thread) {
-
+
// Need to get references to:
- // - newTasksMayBeScheduled field
+ // in Sun/Oracle JDK:
+ // - newTasksMayBeScheduled field (in java.util.TimerThread)
// - queue field
// - queue.clear()
-
+ // in IBM JDK, Apache Harmony:
+ // - cancel() method (in java.util.Timer$TimerImpl)
+
try {
- Field newTasksMayBeScheduledField =
- thread.getClass().getDeclaredField("newTasksMayBeScheduled");
- newTasksMayBeScheduledField.setAccessible(true);
- Field queueField = thread.getClass().getDeclaredField("queue");
- queueField.setAccessible(true);
-
- Object queue = queueField.get(thread);
-
- Method clearMethod = queue.getClass().getDeclaredMethod("clear");
- clearMethod.setAccessible(true);
-
- synchronized(queue) {
- newTasksMayBeScheduledField.setBoolean(thread, false);
- clearMethod.invoke(queue);
- queue.notify(); // In case queue was already empty.
+
+ try {
+ Field newTasksMayBeScheduledField =
+ thread.getClass().getDeclaredField("newTasksMayBeScheduled");
+ newTasksMayBeScheduledField.setAccessible(true);
+ Field queueField = thread.getClass().getDeclaredField("queue");
+ queueField.setAccessible(true);
+
+ Object queue = queueField.get(thread);
+
+ Method clearMethod = queue.getClass().getDeclaredMethod("clear");
+ clearMethod.setAccessible(true);
+
+ synchronized(queue) {
+ newTasksMayBeScheduledField.setBoolean(thread, false);
+ clearMethod.invoke(queue);
+ queue.notify(); // In case queue was already empty.
+ }
+
+ }catch (NoSuchFieldException nfe){
+ Method cancelMethod = thread.getClass().getDeclaredMethod("cancel");
+ synchronized(thread) {
+ cancelMethod.setAccessible(true);
+ cancelMethod.invoke(thread);
+ }
}
-
+
log.error(sm.getString("webappClassLoader.warnTimerThread",
contextName, thread.getName()));
- } catch (NoSuchFieldException e) {
- log.warn(sm.getString(
- "webappClassLoader.stopTimerThreadFail",
- thread.getName(), contextName), e);
} catch (IllegalAccessException e) {
log.warn(sm.getString(
"webappClassLoader.stopTimerThreadFail",
@@ -2340,17 +2366,27 @@ public class WebappClassLoader
Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = tlmClass.getDeclaredField("table");
tableField.setAccessible(true);
-
+ Method expungeStaleEntriesMethod = tlmClass.getDeclaredMethod("expungeStaleEntries");
+ expungeStaleEntriesMethod.setAccessible(true);
+
for (int i = 0; i < threads.length; i++) {
Object threadLocalMap;
if (threads[i] != null) {
+
// Clear the first map
threadLocalMap = threadLocalsField.get(threads[i]);
- clearThreadLocalMap(threadLocalMap, tableField);
+ if (null != threadLocalMap){
+ expungeStaleEntriesMethod.invoke(threadLocalMap);
+ checkThreadLocalMapForLeaks(threadLocalMap, tableField);
+ }
+
// Clear the second map
threadLocalMap =
inheritableThreadLocalsField.get(threads[i]);
- clearThreadLocalMap(threadLocalMap, tableField);
+ if (null != threadLocalMap){
+ expungeStaleEntriesMethod.invoke(threadLocalMap);
+ checkThreadLocalMapForLeaks(threadLocalMap, tableField);
+ }
}
}
} catch (SecurityException e) {
@@ -2383,7 +2419,7 @@ public class WebappClassLoader
* points to the internal table to save re-calculating it on every
* call to this method.
*/
- private void clearThreadLocalMap(Object map, Field internalTableField)
+ private void checkThreadLocalMapForLeaks(Object map, Field internalTableField)
throws NoSuchMethodException, IllegalAccessException,
NoSuchFieldException, InvocationTargetException {
if (map != null) {
Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=1356198&r1=1356197&r2=1356198&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Mon Jul 2 12:04:11 2012
@@ -124,6 +124,11 @@
<code>java.lang.String</code>. (markt)
</fix>
<add>
+ <bug>52850</bug>: Extend memory leak prevention and detection code to
+ work with IBM as well as Oracle JVMs. Based on a patch provided by
+ Rohit Kelapure. (kkolinko)
+ </add>
+ <add>
<bug>52996</bug>: In <code>StandardThreadExecutor</code>:
Add the ability to configure a job queue size
(<code>maxQueueSize</code> attribute).
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org