ASF Bugzilla – Attachment 28433 Details for
Bug 52850
Various miscellaneous fixes to Tomcat Memory Leak Detection code
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
src code fixes to WebappClassLoader and new tests for memory leak detection
52850-1.diff (text/plain), 8.12 KB, created by
Rohit Kelapure
on 2012-03-07 15:02:53 UTC
(
hide
)
Description:
src code fixes to WebappClassLoader and new tests for memory leak detection
Filename:
MIME Type:
Creator:
Rohit Kelapure
Created:
2012-03-07 15:02:53 UTC
Size:
8.12 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P tomcat-8.0.x >Index: java/org/apache/catalina/loader/WebappClassLoader.java >=================================================================== >--- java/org/apache/catalina/loader/WebappClassLoader.java (revision 1297262) >+++ java/org/apache/catalina/loader/WebappClassLoader.java (working copy) >@@ -27,6 +27,7 @@ > import java.lang.ref.Reference; > import java.lang.ref.WeakReference; > import java.lang.reflect.Field; >+import java.lang.reflect.InvocationTargetException; > import java.lang.reflect.Method; > import java.lang.reflect.Modifier; > import java.net.MalformedURLException; >@@ -2244,8 +2245,7 @@ > } > > // TimerThread can be stopped safely so treat separately >- if (thread.getClass().getName().equals( >- "java.util.TimerThread") && >+ if (thread.getClass().getName().startsWith("java.util.Timer") && > clearReferencesStopTimerThreads) { > clearReferencesStopTimerThread(thread); > continue; >@@ -2268,20 +2268,28 @@ > // 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); > >- if (target != null && >- target.getClass().getCanonicalName().equals( >- "java.util.concurrent.ThreadPoolExecutor.Worker")) { >- Field executorField = >- target.getClass().getDeclaredField("this$0"); >- executorField.setAccessible(true); >- Object executor = executorField.get(target); >- if (executor instanceof ThreadPoolExecutor) { >- ((ThreadPoolExecutor) executor).shutdownNow(); >+ Field targetField = null; >+ try { >+ targetField = thread.getClass().getDeclaredField("target"); >+ }catch (NoSuchFieldException nfe){ >+ targetField = thread.getClass().getDeclaredField("runnable"); >+ } >+ if (null != targetField){ >+ targetField.setAccessible(true); >+ Object target = targetField.get(thread); >+ >+ if (target != null && >+ target.getClass().getCanonicalName() != null >+ && target.getClass().getCanonicalName().equals( >+ "java.util.concurrent.ThreadPoolExecutor.Worker")) { >+ Field executorField = >+ target.getClass().getDeclaredField("this$0"); >+ executorField.setAccessible(true); >+ Object executor = executorField.get(target); >+ if (executor instanceof ThreadPoolExecutor) { >+ ((ThreadPoolExecutor) executor).shutdownNow(); >+ } > } > } > } catch (SecurityException e) { >@@ -2350,21 +2358,33 @@ > // - queue.clear() > > try { >- Field newTasksMayBeScheduledField = >- thread.getClass().getDeclaredField("newTasksMayBeScheduled"); >- newTasksMayBeScheduledField.setAccessible(true); >- Field queueField = thread.getClass().getDeclaredField("queue"); >- queueField.setAccessible(true); > >- Object queue = queueField.get(thread); >+ try { >+ Field newTasksMayBeScheduledField = >+ thread.getClass().getDeclaredField("newTasksMayBeScheduled"); >+ newTasksMayBeScheduledField.setAccessible(true); >+ Field queueField = thread.getClass().getDeclaredField("queue"); >+ queueField.setAccessible(true); > >- Method clearMethod = queue.getClass().getDeclaredMethod("clear"); >- clearMethod.setAccessible(true); >+ Object queue = queueField.get(thread); > >- synchronized(queue) { >- newTasksMayBeScheduledField.setBoolean(thread, false); >- clearMethod.invoke(queue); >- queue.notify(); // In case queue was already empty. >+ 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"); >+ if (null != cancelMethod){ >+ synchronized(thread) { >+ cancelMethod.setAccessible(true); >+ cancelMethod.invoke(thread); >+ } >+ } > } > > log.error(sm.getString("webappClassLoader.warnTimerThread", >@@ -2394,21 +2414,29 @@ > inheritableThreadLocalsField.setAccessible(true); > // Make the underlying array of ThreadLoad.ThreadLocalMap.Entry objects > // accessible >- Class<?> tlmClass = >- Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); >+ Class<?> tlmClass = 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]); >- checkThreadLocalMapForLeaks(threadLocalMap, tableField); >+ if (null != threadLocalMap){ >+ expungeStaleEntriesMethod.invoke(threadLocalMap); >+ checkThreadLocalMapForLeaks(threadLocalMap, tableField); >+ } >+ > // Clear the second map >- threadLocalMap = >- inheritableThreadLocalsField.get(threads[i]); >- checkThreadLocalMapForLeaks(threadLocalMap, tableField); >+ threadLocalMap =inheritableThreadLocalsField.get(threads[i]); >+ if (null != threadLocalMap){ >+ expungeStaleEntriesMethod.invoke(threadLocalMap); >+ checkThreadLocalMapForLeaks(threadLocalMap, tableField); >+ } > } > } > } catch (SecurityException e) { >@@ -2426,6 +2454,12 @@ > } catch (IllegalAccessException e) { > log.warn(sm.getString("webappClassLoader.checkThreadLocalsForLeaksFail", > contextName), e); >+ } catch (InvocationTargetException e) { >+ log.warn(sm.getString("webappClassLoader.checkThreadLocalsForLeaksFail", >+ contextName), e); >+ } catch (NoSuchMethodException e) { >+ log.warn(sm.getString("webappClassLoader.checkThreadLocalsForLeaksFail", >+ contextName), e); > } > } > >@@ -2527,7 +2561,7 @@ > clazz = o.getClass(); > } > >- ClassLoader cl = clazz.getClassLoader(); >+ ClassLoader cl = this; > while (cl != null) { > if(cl == this) { > return true;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 52850
:
28433
|
28434
|
28442
|
28893