/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.activemq.bugs.embedded; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.log4j.Logger; public class ThreadExplorer { static Logger logger = Logger.getLogger(ThreadExplorer.class); public static Thread[] listThreads() { int nThreads = Thread.activeCount(); Thread ret[] = new Thread[nThreads]; Thread.enumerate(ret); return ret; } /** * Helper function to access a thread per name (ignoring case) * * @param name * @return */ public static Thread fetchThread(String name) { Thread[] threadArray = listThreads(); // for (Thread t : threadArray) for (int i = 0; i < threadArray.length; i++) { Thread t = threadArray[i]; if (t.getName().equalsIgnoreCase(name)) return t; } return null; } /** * Allow for killing threads * * @param threadName * @param isStarredExp * (regular expressions with *) */ @SuppressWarnings("deprecation") public static int kill(String threadName, boolean isStarredExp, String motivation) { String me = "ThreadExplorer.kill: "; if (logger.isDebugEnabled()) { logger.debug("Entering " + me + " with " + threadName + " isStarred: " + isStarredExp); } int ret = 0; Pattern mypattern = null; if (isStarredExp) { String realreg = threadName.toLowerCase().replaceAll("\\*", "\\.\\*"); mypattern = Pattern.compile(realreg); } Thread[] threads = listThreads(); for (int i = 0; i < threads.length; i++) { Thread thread = threads[i]; if (thread == null) continue; // kill the thread unless it is not current thread boolean matches = false; if (isStarredExp) { Matcher matcher = mypattern.matcher(thread.getName().toLowerCase()); matches = matcher.matches(); } else { matches = (thread.getName().equalsIgnoreCase(threadName)); } if (matches && (Thread.currentThread() != thread) && !thread.getName().equals("main")) { if (logger.isInfoEnabled()) logger.info("Killing thread named [" + thread.getName() + "]"); // , removing its uncaught // exception handler to // avoid ThreadDeath // exception tracing // "+motivation ); ret++; // PK leaving uncaught exception handler otherwise master push // cannot recover from this error // thread.setUncaughtExceptionHandler(null); try { thread.stop(); } catch (ThreadDeath e) { logger.warn("Thread already death.", e); } } } return ret; } public static String show(String title) { StringBuffer out = new StringBuffer(); Thread[] threadArray = ThreadExplorer.listThreads(); out.append(title + "\n"); for (int i = 0; i < threadArray.length; i++) { Thread thread = threadArray[i]; if (thread != null) { out.append("* [" + thread.getName() + "] " + (thread.isDaemon() ? "(Daemon)" : "") + " Group: " + (thread.getThreadGroup() != null ? thread.getThreadGroup().getName() : "") + "\n"); } else { out.append("* ThreadDeath: " + thread + "\n"); } } return out.toString(); } public static int active() { int count = 0; Thread[] threadArray = ThreadExplorer.listThreads(); for (int i = 0; i < threadArray.length; i++) { Thread thread = threadArray[i]; if (thread != null) { count++; } } return count; } }