View | Details | Raw Unified | Return to bug 52850
Collapse All | Expand All

(-)java/org/apache/catalina/loader/WebappClassLoader.java (-35 / +73 lines)
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-2539 Link Here
2527
            clazz = o.getClass();
2561
            clazz = o.getClass();
2528
        }
2562
        }
2529
2563
2530
        ClassLoader cl = clazz.getClassLoader();
2564
        ClassLoader oCL = clazz.getClassLoader();
2565
        ClassLoader cl = this;
2531
        while (cl != null) {
2566
        while (cl != null) {
2532
            if(cl == this) {
2567
            if(cl == oCL) {
2533
                return true;
2568
                return true;
2534
            }
2569
            }
2535
            cl = cl.getParent();
2570
            cl = cl.getParent();
2536
        }
2571
        }
2572
2573
        if (cl == oCL) return true;
2574
2537
        return false;
2575
        return false;
2538
    }
2576
    }
2539
2577

Return to bug 52850