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);
}
}
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()));
}
}
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();
}
}
}
Aggregations