Search in sources :

Example 1 with InaccessibleObjectException

use of java.lang.reflect.InaccessibleObjectException in project tomcat by apache.

the class WebappClassLoaderBase method checkThreadLocalsForLeaks.

private void checkThreadLocalsForLeaks() {
    Thread[] threads = getThreads();
    try {
        // Make the fields in the Thread class that store ThreadLocals
        // accessible
        Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
        threadLocalsField.setAccessible(true);
        Field inheritableThreadLocalsField = Thread.class.getDeclaredField("inheritableThreadLocals");
        inheritableThreadLocalsField.setAccessible(true);
        // Make the underlying array of ThreadLoad.ThreadLocalMap.Entry objects
        // accessible
        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 (Thread thread : threads) {
            Object threadLocalMap;
            if (thread != null) {
                // Clear the first map
                threadLocalMap = threadLocalsField.get(thread);
                if (null != threadLocalMap) {
                    expungeStaleEntriesMethod.invoke(threadLocalMap);
                    checkThreadLocalMapForLeaks(threadLocalMap, tableField);
                }
                // Clear the second map
                threadLocalMap = inheritableThreadLocalsField.get(thread);
                if (null != threadLocalMap) {
                    expungeStaleEntriesMethod.invoke(threadLocalMap);
                    checkThreadLocalMapForLeaks(threadLocalMap, tableField);
                }
            }
        }
    } catch (InaccessibleObjectException e) {
        // Must be running on without the necessary command line options.
        log.warn(sm.getString("webappClassLoader.addExportsThreadLocal", this.getClass().getModule().getName()));
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        log.warn(sm.getString("webappClassLoader.checkThreadLocalsForLeaksFail", getContextName()), t);
    }
}
Also used : Field(java.lang.reflect.Field) InaccessibleObjectException(java.lang.reflect.InaccessibleObjectException) Method(java.lang.reflect.Method)

Example 2 with InaccessibleObjectException

use of java.lang.reflect.InaccessibleObjectException in project tomcat by apache.

the class WebappClassLoaderBase method clearReferencesRmiTargets.

/**
 * This depends on the internals of the Sun JVM so it does everything by
 * reflection.
 */
private void clearReferencesRmiTargets() {
    try {
        // Need access to the ccl field of sun.rmi.transport.Target to find
        // the leaks
        Class<?> objectTargetClass = Class.forName("sun.rmi.transport.Target");
        Field cclField = objectTargetClass.getDeclaredField("ccl");
        cclField.setAccessible(true);
        // Need access to the stub field to report the leaks
        Field stubField = objectTargetClass.getDeclaredField("stub");
        stubField.setAccessible(true);
        // Clear the objTable map
        Class<?> objectTableClass = Class.forName("sun.rmi.transport.ObjectTable");
        Field objTableField = objectTableClass.getDeclaredField("objTable");
        objTableField.setAccessible(true);
        Object objTable = objTableField.get(null);
        if (objTable == null) {
            return;
        }
        Field tableLockField = objectTableClass.getDeclaredField("tableLock");
        tableLockField.setAccessible(true);
        Object tableLock = tableLockField.get(null);
        synchronized (tableLock) {
            // Iterate over the values in the table
            if (objTable instanceof Map<?, ?>) {
                Iterator<?> iter = ((Map<?, ?>) objTable).values().iterator();
                while (iter.hasNext()) {
                    Object obj = iter.next();
                    Object cclObject = cclField.get(obj);
                    if (this == cclObject) {
                        iter.remove();
                        Object stubObject = stubField.get(obj);
                        log.error(sm.getString("webappClassLoader.clearRmi", stubObject.getClass().getName(), stubObject));
                    }
                }
            }
            // Clear the implTable map
            Field implTableField = objectTableClass.getDeclaredField("implTable");
            implTableField.setAccessible(true);
            Object implTable = implTableField.get(null);
            if (implTable == null) {
                return;
            }
            // Iterate over the values in the table
            if (implTable instanceof Map<?, ?>) {
                Iterator<?> iter = ((Map<?, ?>) implTable).values().iterator();
                while (iter.hasNext()) {
                    Object obj = iter.next();
                    Object cclObject = cclField.get(obj);
                    if (this == cclObject) {
                        iter.remove();
                    }
                }
            }
        }
    } catch (ClassNotFoundException e) {
        log.info(sm.getString("webappClassLoader.clearRmiInfo", getContextName()), e);
    } catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
        log.warn(sm.getString("webappClassLoader.clearRmiFail", getContextName()), e);
    } catch (InaccessibleObjectException e) {
        // Must be running on without the necessary command line options.
        log.warn(sm.getString("webappClassLoader.addExportsRmi", this.getClass().getModule().getName()));
    }
}
Also used : Field(java.lang.reflect.Field) InaccessibleObjectException(java.lang.reflect.InaccessibleObjectException) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Example 3 with InaccessibleObjectException

use of java.lang.reflect.InaccessibleObjectException in project tomcat by apache.

the class WebappClassLoaderBase method clearReferencesThreads.

// thread.stop()
@SuppressWarnings("deprecation")
private void clearReferencesThreads() {
    Thread[] threads = getThreads();
    List<Thread> threadsToStop = new ArrayList<>();
    // Iterate over the set of threads
    for (Thread thread : threads) {
        if (thread != null) {
            ClassLoader ccl = thread.getContextClassLoader();
            if (ccl == this) {
                // Don't warn about this thread
                if (thread == Thread.currentThread()) {
                    continue;
                }
                final String threadName = thread.getName();
                // JVM controlled threads
                ThreadGroup tg = thread.getThreadGroup();
                if (tg != null && JVM_THREAD_GROUP_NAMES.contains(tg.getName())) {
                    // HttpClient keep-alive threads
                    if (clearReferencesHttpClientKeepAliveThread && threadName.equals("Keep-Alive-Timer")) {
                        thread.setContextClassLoader(parent);
                        log.debug(sm.getString("webappClassLoader.checkThreadsHttpClient"));
                    }
                    // Don't warn about remaining JVM controlled threads
                    continue;
                }
                // Skip threads that have already died
                if (!thread.isAlive()) {
                    continue;
                }
                // "java.util.Timer$TimerImpl" in Apache Harmony and in IBM JDK
                if (thread.getClass().getName().startsWith("java.util.Timer") && clearReferencesStopTimerThreads) {
                    clearReferencesStopTimerThread(thread);
                    continue;
                }
                if (isRequestThread(thread)) {
                    log.warn(sm.getString("webappClassLoader.stackTraceRequestThread", getContextName(), threadName, getStackTrace(thread)));
                } else {
                    log.warn(sm.getString("webappClassLoader.stackTrace", getContextName(), threadName, getStackTrace(thread)));
                }
                // configured to do so
                if (!clearReferencesStopThreads) {
                    continue;
                }
                // If the thread has been started via an executor, try
                // shutting down the executor
                boolean usingExecutor = false;
                try {
                    // 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;
                        }
                    }
                    // internal fork.
                    if (target != null && target.getClass().getCanonicalName() != null && (target.getClass().getCanonicalName().equals("org.apache.tomcat.util.threads.ThreadPoolExecutor.Worker") || 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();
                            usingExecutor = true;
                        } else if (executor instanceof java.util.concurrent.ThreadPoolExecutor) {
                            ((java.util.concurrent.ThreadPoolExecutor) executor).shutdownNow();
                            usingExecutor = true;
                        }
                    }
                } catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException | InaccessibleObjectException e) {
                    log.warn(sm.getString("webappClassLoader.stopThreadFail", thread.getName(), getContextName()), e);
                }
                // them here.
                if (!usingExecutor && !thread.isInterrupted()) {
                    thread.interrupt();
                }
                // Threads are expected to take a short time to stop after
                // being interrupted. Make a note of all threads that are
                // expected to stop to enable them to be checked at the end
                // of this method.
                threadsToStop.add(thread);
            }
        }
    }
    // If thread stopping is enabled, threads should have been stopped above
    // when the executor was shut down or the thread was interrupted but
    // that depends on the thread correctly handling the interrupt. Check
    // each thread and if any are still running give all threads up to a
    // total of 2 seconds to shutdown.
    int count = 0;
    for (Thread t : threadsToStop) {
        while (t.isAlive() && count < 100) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                // Quit the while loop
                break;
            }
            count++;
        }
        if (t.isAlive()) {
            // This method is deprecated and for good reason. This is
            // very risky code but is the only option at this point.
            // A *very* good reason for apps to do this clean-up
            // themselves.
            t.stop();
        }
    }
}
Also used : CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) Field(java.lang.reflect.Field) InaccessibleObjectException(java.lang.reflect.InaccessibleObjectException) URLClassLoader(java.net.URLClassLoader) InstrumentableClassLoader(org.apache.tomcat.InstrumentableClassLoader) ThreadPoolExecutor(org.apache.tomcat.util.threads.ThreadPoolExecutor)

Aggregations

Field (java.lang.reflect.Field)3 InaccessibleObjectException (java.lang.reflect.InaccessibleObjectException)3 Method (java.lang.reflect.Method)1 URLClassLoader (java.net.URLClassLoader)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1 InstrumentableClassLoader (org.apache.tomcat.InstrumentableClassLoader)1 ThreadPoolExecutor (org.apache.tomcat.util.threads.ThreadPoolExecutor)1