Lines 27-32
Link Here
|
27 |
import java.lang.ref.Reference; |
27 |
import java.lang.ref.Reference; |
28 |
import java.lang.ref.WeakReference; |
28 |
import java.lang.ref.WeakReference; |
29 |
import java.lang.reflect.Field; |
29 |
import java.lang.reflect.Field; |
|
|
30 |
import java.lang.reflect.InvocationTargetException; |
30 |
import java.lang.reflect.Method; |
31 |
import java.lang.reflect.Method; |
31 |
import java.lang.reflect.Modifier; |
32 |
import java.lang.reflect.Modifier; |
32 |
import java.net.MalformedURLException; |
33 |
import java.net.MalformedURLException; |
Lines 2244-2251
Link Here
|
2244 |
} |
2245 |
} |
2245 |
|
2246 |
|
2246 |
// TimerThread can be stopped safely so treat separately |
2247 |
// TimerThread can be stopped safely so treat separately |
2247 |
if (thread.getClass().getName().equals( |
2248 |
if (thread.getClass().getName().startsWith("java.util.Timer") && |
2248 |
"java.util.TimerThread") && |
|
|
2249 |
clearReferencesStopTimerThreads) { |
2249 |
clearReferencesStopTimerThreads) { |
2250 |
clearReferencesStopTimerThread(thread); |
2250 |
clearReferencesStopTimerThread(thread); |
2251 |
continue; |
2251 |
continue; |
Lines 2268-2287
Link Here
|
2268 |
// If the thread has been started via an executor, try |
2268 |
// If the thread has been started via an executor, try |
2269 |
// shutting down the executor |
2269 |
// shutting down the executor |
2270 |
try { |
2270 |
try { |
2271 |
Field targetField = |
|
|
2272 |
thread.getClass().getDeclaredField("target"); |
2273 |
targetField.setAccessible(true); |
2274 |
Object target = targetField.get(thread); |
2275 |
|
2271 |
|
2276 |
if (target != null && |
2272 |
Field targetField = null; |
2277 |
target.getClass().getCanonicalName().equals( |
2273 |
try { |
2278 |
"java.util.concurrent.ThreadPoolExecutor.Worker")) { |
2274 |
targetField = thread.getClass().getDeclaredField("target"); |
2279 |
Field executorField = |
2275 |
}catch (NoSuchFieldException nfe){ |
2280 |
target.getClass().getDeclaredField("this$0"); |
2276 |
targetField = thread.getClass().getDeclaredField("runnable"); |
2281 |
executorField.setAccessible(true); |
2277 |
} |
2282 |
Object executor = executorField.get(target); |
2278 |
if (null != targetField){ |
2283 |
if (executor instanceof ThreadPoolExecutor) { |
2279 |
targetField.setAccessible(true); |
2284 |
((ThreadPoolExecutor) executor).shutdownNow(); |
2280 |
Object target = targetField.get(thread); |
|
|
2281 |
|
2282 |
if (target != null && |
2283 |
target.getClass().getCanonicalName() != null |
2284 |
&& target.getClass().getCanonicalName().equals( |
2285 |
"java.util.concurrent.ThreadPoolExecutor.Worker")) { |
2286 |
Field executorField = |
2287 |
target.getClass().getDeclaredField("this$0"); |
2288 |
executorField.setAccessible(true); |
2289 |
Object executor = executorField.get(target); |
2290 |
if (executor instanceof ThreadPoolExecutor) { |
2291 |
((ThreadPoolExecutor) executor).shutdownNow(); |
2292 |
} |
2285 |
} |
2293 |
} |
2286 |
} |
2294 |
} |
2287 |
} catch (SecurityException e) { |
2295 |
} catch (SecurityException e) { |
Lines 2350-2370
Link Here
|
2350 |
// - queue.clear() |
2358 |
// - queue.clear() |
2351 |
|
2359 |
|
2352 |
try { |
2360 |
try { |
2353 |
Field newTasksMayBeScheduledField = |
|
|
2354 |
thread.getClass().getDeclaredField("newTasksMayBeScheduled"); |
2355 |
newTasksMayBeScheduledField.setAccessible(true); |
2356 |
Field queueField = thread.getClass().getDeclaredField("queue"); |
2357 |
queueField.setAccessible(true); |
2358 |
|
2361 |
|
2359 |
Object queue = queueField.get(thread); |
2362 |
try { |
|
|
2363 |
Field newTasksMayBeScheduledField = |
2364 |
thread.getClass().getDeclaredField("newTasksMayBeScheduled"); |
2365 |
newTasksMayBeScheduledField.setAccessible(true); |
2366 |
Field queueField = thread.getClass().getDeclaredField("queue"); |
2367 |
queueField.setAccessible(true); |
2360 |
|
2368 |
|
2361 |
Method clearMethod = queue.getClass().getDeclaredMethod("clear"); |
2369 |
Object queue = queueField.get(thread); |
2362 |
clearMethod.setAccessible(true); |
|
|
2363 |
|
2370 |
|
2364 |
synchronized(queue) { |
2371 |
Method clearMethod = queue.getClass().getDeclaredMethod("clear"); |
2365 |
newTasksMayBeScheduledField.setBoolean(thread, false); |
2372 |
clearMethod.setAccessible(true); |
2366 |
clearMethod.invoke(queue); |
2373 |
|
2367 |
queue.notify(); // In case queue was already empty. |
2374 |
synchronized(queue) { |
|
|
2375 |
newTasksMayBeScheduledField.setBoolean(thread, false); |
2376 |
clearMethod.invoke(queue); |
2377 |
queue.notify(); // In case queue was already empty. |
2378 |
} |
2379 |
|
2380 |
}catch (NoSuchFieldException nfe){ |
2381 |
Method cancelMethod = thread.getClass().getDeclaredMethod("cancel"); |
2382 |
if (null != cancelMethod){ |
2383 |
synchronized(thread) { |
2384 |
cancelMethod.setAccessible(true); |
2385 |
cancelMethod.invoke(thread); |
2386 |
} |
2387 |
} |
2368 |
} |
2388 |
} |
2369 |
|
2389 |
|
2370 |
log.error(sm.getString("webappClassLoader.warnTimerThread", |
2390 |
log.error(sm.getString("webappClassLoader.warnTimerThread", |
Lines 2394-2414
Link Here
|
2394 |
inheritableThreadLocalsField.setAccessible(true); |
2414 |
inheritableThreadLocalsField.setAccessible(true); |
2395 |
// Make the underlying array of ThreadLoad.ThreadLocalMap.Entry objects |
2415 |
// Make the underlying array of ThreadLoad.ThreadLocalMap.Entry objects |
2396 |
// accessible |
2416 |
// accessible |
2397 |
Class<?> tlmClass = |
2417 |
Class<?> tlmClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); |
2398 |
Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); |
|
|
2399 |
Field tableField = tlmClass.getDeclaredField("table"); |
2418 |
Field tableField = tlmClass.getDeclaredField("table"); |
2400 |
tableField.setAccessible(true); |
2419 |
tableField.setAccessible(true); |
|
|
2420 |
Method expungeStaleEntriesMethod = tlmClass.getDeclaredMethod("expungeStaleEntries"); |
2421 |
expungeStaleEntriesMethod.setAccessible(true); |
2401 |
|
2422 |
|
2402 |
for (int i = 0; i < threads.length; i++) { |
2423 |
for (int i = 0; i < threads.length; i++) { |
2403 |
Object threadLocalMap; |
2424 |
Object threadLocalMap; |
2404 |
if (threads[i] != null) { |
2425 |
if (threads[i] != null) { |
|
|
2426 |
|
2405 |
// Clear the first map |
2427 |
// Clear the first map |
2406 |
threadLocalMap = threadLocalsField.get(threads[i]); |
2428 |
threadLocalMap = threadLocalsField.get(threads[i]); |
2407 |
checkThreadLocalMapForLeaks(threadLocalMap, tableField); |
2429 |
if (null != threadLocalMap){ |
|
|
2430 |
expungeStaleEntriesMethod.invoke(threadLocalMap); |
2431 |
checkThreadLocalMapForLeaks(threadLocalMap, tableField); |
2432 |
} |
2433 |
|
2408 |
// Clear the second map |
2434 |
// Clear the second map |
2409 |
threadLocalMap = |
2435 |
threadLocalMap =inheritableThreadLocalsField.get(threads[i]); |
2410 |
inheritableThreadLocalsField.get(threads[i]); |
2436 |
if (null != threadLocalMap){ |
2411 |
checkThreadLocalMapForLeaks(threadLocalMap, tableField); |
2437 |
expungeStaleEntriesMethod.invoke(threadLocalMap); |
|
|
2438 |
checkThreadLocalMapForLeaks(threadLocalMap, tableField); |
2439 |
} |
2412 |
} |
2440 |
} |
2413 |
} |
2441 |
} |
2414 |
} catch (SecurityException e) { |
2442 |
} catch (SecurityException e) { |
Lines 2426-2431
Link Here
|
2426 |
} catch (IllegalAccessException e) { |
2454 |
} catch (IllegalAccessException e) { |
2427 |
log.warn(sm.getString("webappClassLoader.checkThreadLocalsForLeaksFail", |
2455 |
log.warn(sm.getString("webappClassLoader.checkThreadLocalsForLeaksFail", |
2428 |
contextName), e); |
2456 |
contextName), e); |
|
|
2457 |
} catch (InvocationTargetException e) { |
2458 |
log.warn(sm.getString("webappClassLoader.checkThreadLocalsForLeaksFail", |
2459 |
contextName), e); |
2460 |
} catch (NoSuchMethodException e) { |
2461 |
log.warn(sm.getString("webappClassLoader.checkThreadLocalsForLeaksFail", |
2462 |
contextName), e); |
2429 |
} |
2463 |
} |
2430 |
} |
2464 |
} |
2431 |
|
2465 |
|
Lines 2527-2533
Link Here
|
2527 |
clazz = o.getClass(); |
2561 |
clazz = o.getClass(); |
2528 |
} |
2562 |
} |
2529 |
|
2563 |
|
2530 |
ClassLoader cl = clazz.getClassLoader(); |
2564 |
ClassLoader cl = this; |
2531 |
while (cl != null) { |
2565 |
while (cl != null) { |
2532 |
if(cl == this) { |
2566 |
if(cl == this) { |
2533 |
return true; |
2567 |
return true; |