/** * Tries to enable CPU time measurement for threads. Not all JVMs support this feature. * * @return <code>true</code> if the JVM supports time measurement for threads and the feature * could be enabled, <code>false</code> otherwise. */ public static final boolean enableThreadCpuTimeMeasurement() { if (tbe.isThreadCpuTimeSupported()) { tbe.setThreadCpuTimeEnabled(true); return true; } return false; }
@Override public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { validator.validate(operation); ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); try { long id = operation.require(PlatformMBeanConstants.ID).asLong(); ThreadInfo info = null; if (operation.hasDefined(PlatformMBeanConstants.MAX_DEPTH)) { info = mbean.getThreadInfo(id, operation.require(PlatformMBeanConstants.MAX_DEPTH).asInt()); } else { info = mbean.getThreadInfo(id); } final ModelNode result = context.getResult(); if (info != null) { result.set(PlatformMBeanUtil.getDetypedThreadInfo(info, mbean.isThreadCpuTimeSupported())); } } catch (SecurityException e) { throw new OperationFailedException(new ModelNode().set(e.toString())); } context.completeStep(); }
/** * Update the information about completed thread that ran for runtime in milliseconds * * <p>This method updates all of the key timing and tracking information in the factory so that * thread can be retired. After this call the factory shouldn't have a pointer to the thread any * longer * * @param thread the thread whose information we are updating */ @Ensures({"getTotalTime() >= old(getTotalTime())"}) public synchronized void threadIsDone(final Thread thread) { nThreadsAnalyzed++; if (DEBUG) logger.warn("UpdateThreadInfo called"); final long threadID = thread.getId(); final ThreadInfo info = bean.getThreadInfo(thread.getId()); final long totalTimeNano = bean.getThreadCpuTime(threadID); final long userTimeNano = bean.getThreadUserTime(threadID); final long systemTimeNano = totalTimeNano - userTimeNano; final long userTimeInMilliseconds = nanoToMilli(userTimeNano); final long systemTimeInMilliseconds = nanoToMilli(systemTimeNano); if (info != null) { if (DEBUG) logger.warn( "Updating thread with user runtime " + userTimeInMilliseconds + " and system runtime " + systemTimeInMilliseconds + " of which blocked " + info.getBlockedTime() + " and waiting " + info.getWaitedTime()); incTimes(State.BLOCKING, info.getBlockedTime()); incTimes(State.WAITING, info.getWaitedTime()); incTimes(State.USER_CPU, userTimeInMilliseconds); incTimes(State.WAITING_FOR_IO, systemTimeInMilliseconds); } }
public static void main(String args[]) { // get top-level thread group ThreadGroup top = Thread.currentThread().getThreadGroup(); ThreadGroup parent; do { parent = top.getParent(); if (parent != null) top = parent; } while (parent != null); // get the thread count int activeCount = top.activeCount(); Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces(); ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); int threadCount = threadBean.getThreadCount(); long[] threadIds = threadBean.getAllThreadIds(); System.out.println("ThreadGroup: " + activeCount + " active thread(s)"); System.out.println("Thread: " + stackTraces.size() + " stack trace(s) returned"); System.out.println("ThreadMXBean: " + threadCount + " live threads(s)"); System.out.println("ThreadMXBean: " + threadIds.length + " thread Id(s)"); // check results are consistent boolean failed = false; if (activeCount != stackTraces.size()) failed = true; if (activeCount != threadCount) failed = true; if (activeCount != threadIds.length) failed = true; if (failed) { throw new RuntimeException("inconsistent results"); } }
private void doThreadUpdates() { ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); long threadIds[] = threadMXBean.getAllThreadIds(); ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadIds, 0); int threadsNew = 0; int threadsRunnable = 0; int threadsBlocked = 0; int threadsWaiting = 0; int threadsTimedWaiting = 0; int threadsTerminated = 0; for (ThreadInfo threadInfo : threadInfos) { // threadInfo is null if the thread is not alive or doesn't exist if (threadInfo == null) continue; Thread.State state = threadInfo.getThreadState(); if (state == NEW) { threadsNew++; } else if (state == RUNNABLE) { threadsRunnable++; } else if (state == BLOCKED) { threadsBlocked++; } else if (state == WAITING) { threadsWaiting++; } else if (state == TIMED_WAITING) { threadsTimedWaiting++; } else if (state == TERMINATED) { threadsTerminated++; } } metrics.setMetric("threadsNew", threadsNew); metrics.setMetric("threadsRunnable", threadsRunnable); metrics.setMetric("threadsBlocked", threadsBlocked); metrics.setMetric("threadsWaiting", threadsWaiting); metrics.setMetric("threadsTimedWaiting", threadsTimedWaiting); metrics.setMetric("threadsTerminated", threadsTerminated); }
private void createRuntimeProps(MemberStateImpl memberState) { Runtime runtime = Runtime.getRuntime(); ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean(); RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean(); ClassLoadingMXBean clMxBean = ManagementFactory.getClassLoadingMXBean(); MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean(); MemoryUsage heapMemory = memoryMxBean.getHeapMemoryUsage(); MemoryUsage nonHeapMemory = memoryMxBean.getNonHeapMemoryUsage(); Map<String, Long> map = new HashMap<String, Long>(); map.put( "runtime.availableProcessors", Integer.valueOf(runtime.availableProcessors()).longValue()); map.put("date.startTime", runtimeMxBean.getStartTime()); map.put("seconds.upTime", runtimeMxBean.getUptime()); map.put("memory.maxMemory", runtime.maxMemory()); map.put("memory.freeMemory", runtime.freeMemory()); map.put("memory.totalMemory", runtime.totalMemory()); map.put("memory.heapMemoryMax", heapMemory.getMax()); map.put("memory.heapMemoryUsed", heapMemory.getUsed()); map.put("memory.nonHeapMemoryMax", nonHeapMemory.getMax()); map.put("memory.nonHeapMemoryUsed", nonHeapMemory.getUsed()); map.put("runtime.totalLoadedClassCount", clMxBean.getTotalLoadedClassCount()); map.put( "runtime.loadedClassCount", Integer.valueOf(clMxBean.getLoadedClassCount()).longValue()); map.put("runtime.unloadedClassCount", clMxBean.getUnloadedClassCount()); map.put("runtime.totalStartedThreadCount", threadMxBean.getTotalStartedThreadCount()); map.put("runtime.threadCount", Integer.valueOf(threadMxBean.getThreadCount()).longValue()); map.put( "runtime.peakThreadCount", Integer.valueOf(threadMxBean.getPeakThreadCount()).longValue()); map.put( "runtime.daemonThreadCount", Integer.valueOf(threadMxBean.getDaemonThreadCount()).longValue()); memberState.setRuntimeProps(map); }
private static Set<Dependency> collectFromDependencyMonitor( ThreadMXBean bean, Serializable locality, Map<Long, ThreadInfo> threadInfos) { HashSet<Dependency> results = new HashSet<Dependency>(); // Convert the held resources into serializable dependencies Set<Dependency<Serializable, Thread>> heldResources = DependencyMonitorManager.getHeldResources(); for (Dependency<Serializable, Thread> dep : heldResources) { Thread thread = dep.getDependsOn(); Serializable resource = dep.getDepender(); ThreadInfo info = threadInfos.get(thread.getId()); if (info == null) { info = bean.getThreadInfo(thread.getId()); } if (info != null) { results.add(new Dependency(resource, new LocalThread(locality, info))); } } Set<Dependency<Thread, Serializable>> blockedThreads = DependencyMonitorManager.getBlockedThreads(); // Convert the blocked threads into serializable dependencies for (Dependency<Thread, Serializable> dep : blockedThreads) { Thread thread = dep.getDepender(); ThreadInfo info = threadInfos.get(thread.getId()); if (info == null) { info = bean.getThreadInfo(thread.getId()); } final Serializable resource = dep.getDependsOn(); results.add(new Dependency(new LocalThread(locality, info), resource)); } return results; }
private long getUserTime() { if (bean.isCurrentThreadCpuTimeSupported()) { return bean.getCurrentThreadUserTime(); } else { throw new RuntimeException("UserTime NOT Supported"); } }
/// The watcher thread - from the Runnable interface. // This has to be pretty anal to avoid monitor lockup, lost // threads, etc. public synchronized void run() { Thread me = Thread.currentThread(); me.setPriority(Thread.MAX_PRIORITY); ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); startTimeInNs = threadMXBean.getCurrentThreadCpuTime(); if (enabled.get()) { do { loop.set(false); try { wait(millis); } catch (InterruptedException e) { } } while (enabled.get() && loop.get()); } if (enabled.get() && targetThread.isAlive()) { isDoneRunning.set(true); printThread(); if (kill) { logger.warn( "Trying to kill thread with id:" + targetThread.getId() + " but did not as it can cause deadlocks etc."); // targetThread.interrupt(); // targetThread.stop(); //Never kill thread - it can cause other problems } done(); isDoneRunning.set(false); } }
@RequestMapping("/dumpThead") @ResponseBody public void doDumpThread(HttpServletRequest request, HttpServletResponse response) { try { String app = request.getParameter("app"); String threadId = request.getParameter("threadId"); ThreadMXBean tBean = JMConnManager.getThreadMBean(app); JSONObject data = new JSONObject(); if (threadId != null) { Long id = Long.valueOf(threadId); ThreadInfo threadInfo = tBean.getThreadInfo(id, Integer.MAX_VALUE); data.put("info", threadInfo.toString()); } else { ThreadInfo[] dumpAllThreads = tBean.dumpAllThreads(false, false); StringBuffer info = new StringBuffer(); for (ThreadInfo threadInfo : dumpAllThreads) { info.append("\n").append(threadInfo); } data.put("info", info); } writeFile(request, response, data); } catch (IOException e) { throw new RuntimeException(e); } }
/** * Returns object of class ‘"proc_time"’ which is a numeric vector of length 5, containing the * user, system, and total elapsed times for the currently running R process, and the cumulative * sum of user and system times of any child processes spawned by it on which it has waited. * * <p>_The ‘user time’ is the CPU time charged for the execution of user instructions of the * calling process. The ‘system time’ is the CPU time charged for execution by the system on * behalf of the calling process._ */ @Builtin("proc.time") public static DoubleVector procTime() { DoubleArrayVector.Builder result = new DoubleArrayVector.Builder(); StringVector.Builder names = new StringVector.Builder(); long totalCPUTime; long userCPUTime; long elapsedTime; // There doesn't seem to be any platform-independent way of accessing // CPU use for the whole JVM process, so we'll have to make do // with the timings for the thread we're running on. // // Additionally, the MX Beans may not be available in all environments, // so we need to fallback to app try { ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); totalCPUTime = threadMXBean.getCurrentThreadCpuTime(); userCPUTime = threadMXBean.getCurrentThreadUserTime(); RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); elapsedTime = runtimeMXBean.getUptime(); } catch (Error e) { // ThreadMXBean is not available in all environments // Specifically, AppEngine will throw variously SecurityErrors or // ClassNotFoundErrors if we try to access these classes userCPUTime = totalCPUTime = java.lang.System.nanoTime(); elapsedTime = new Date().getTime(); } // user.self names.add("user.self"); result.add(userCPUTime / NANOSECONDS_PER_SECOND); // sys.self names.add("sys.self"); result.add((totalCPUTime - userCPUTime) / NANOSECONDS_PER_SECOND); // elapsed // (wall clock time) names.add("elapsed"); result.add(elapsedTime); // AFAIK, we don't have any platform independent way of accessing // this info. // user.child names.add("user.child"); result.add(0); // sys.child names.add("sys.child"); result.add(0); result.setAttribute(Symbols.NAMES, names.build()); result.setAttribute(Symbols.CLASS, StringVector.valueOf("proc_time")); return result.build(); }
private long[] findDeadlockedThreads(ThreadMXBean mbean) { // JDK 1.5 only supports the findMonitorDeadlockedThreads() // method, so you need to comment out the following three lines if (mbean.isSynchronizerUsageSupported()) { return mbean.findDeadlockedThreads(); } return mbean.findMonitorDeadlockedThreads(); }
@IgnoreJRERequirement public static ThreadInfo[] getThreadInfos() { ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); return mbean.getThreadInfo( mbean.getAllThreadIds(), mbean.isObjectMonitorUsageSupported(), mbean.isSynchronizerUsageSupported()); }
public ThreadInfo[] getDeadLocks() { final long[] ids = _tmx.findDeadlockedThreads(); if (ids != null) { return _tmx.getThreadInfo(ids, true, true); } else { return null; } }
// Return thread IDs of deadlocked threads or null if any. // It finds deadlocks involving only monitors if it's a Tiger VM. // Otherwise, it finds deadlocks involving both monitors and // the concurrent locks. public long[] findDeadlockedThreads() throws IOException { ThreadMXBean tm = getThreadMXBean(); if (supportsLockUsage && tm.isSynchronizerUsageSupported()) { return tm.findDeadlockedThreads(); } else { return tm.findMonitorDeadlockedThreads(); } }
/** * Attempts to enable thread contention monitoring. * * @return true if thread contention monitoring is enabled, false otherwise */ protected static boolean enableContentionTimes() { if (!TMX.isThreadContentionMonitoringSupported()) return false; if (TMX.isThreadContentionMonitoringEnabled()) return true; try { TMX.setThreadContentionMonitoringEnabled(true); } catch (Throwable t) { } return TMX.isThreadContentionMonitoringEnabled(); }
public static void main(String[] args) { // 获取Java线程管理MXBean ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); for (ThreadInfo threadInfo : threadInfos) { System.out.println("[" + threadInfo.getThreadId() + " ] " + threadInfo.getThreadName()); } }
public void printTime(String name, Object... parameters) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { start = threadMXB.getCurrentThreadCpuTime(); method.invoke(null, parameters); end = threadMXB.getCurrentThreadCpuTime(); System.out.println("§" + name); System.out.println(end - start); }
@Override public void verify(QueryContext context, String queryString) { if (!context.getSession().isAdmin()) throw new QueryParseException("95050", -1, -1, null); ThreadMXBean bean = ManagementFactory.getThreadMXBean(); if (!bean.isThreadCpuTimeSupported()) throw new QueryParseException("95051", -1, -1, null); if (!bean.isThreadCpuTimeEnabled()) throw new QueryParseException("95051", -1, -1, null); }
public static void main(String[] argv) throws Exception { mbean = newPlatformMXBeanProxy(server, THREAD_MXBEAN_NAME, ThreadMXBean.class); if (!mbean.isSynchronizerUsageSupported()) { System.out.println("Monitoring of synchronizer usage not supported"); return; } thread.setDaemon(true); thread.start(); // wait until myThread acquires mutex and lock owner is set. while (!(mutex.isLocked() && mutex.getLockOwner() == thread)) { try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } } long[] ids = new long[] {thread.getId()}; // validate the local access ThreadInfo[] infos = getThreadMXBean().getThreadInfo(ids, true, true); if (infos.length != 1) { throw new RuntimeException( "Returned ThreadInfo[] of length=" + infos.length + ". Expected to be 1."); } thread.checkThreadInfo(infos[0]); // validate the remote access infos = mbean.getThreadInfo(ids, true, true); if (infos.length != 1) { throw new RuntimeException( "Returned ThreadInfo[] of length=" + infos.length + ". Expected to be 1."); } thread.checkThreadInfo(infos[0]); boolean found = false; infos = mbean.dumpAllThreads(true, true); for (ThreadInfo ti : infos) { if (ti.getThreadId() == thread.getId()) { thread.checkThreadInfo(ti); found = true; } } if (!found) { throw new RuntimeException("No ThreadInfo found for MyThread"); } System.out.println("Test passed"); }
public static String threadDump() { StringBuilder threadDump = new StringBuilder(); ThreadMXBean threadMx = ManagementFactory.getThreadMXBean(); if (threadMx.isObjectMonitorUsageSupported() && threadMx.isSynchronizerUsageSupported()) { // Print lock info if, and only if, both object monitor usage and synchronizer usage are // supported. dumpThreadInfo(threadDump, true, threadMx); } else { dumpThreadInfo(threadDump, false, threadMx); } return threadDump.toString(); }
public static CharSequence getThreadStats( boolean lockedMonitors, boolean lockedSynchronizers, boolean stackTrace) { StringBuilder list = new StringBuilder(); int threadCount = threadMXbean.getThreadCount(); int daemonCount = threadMXbean.getThreadCount(); int nonDaemonCount = threadCount - daemonCount; int peakCount = threadMXbean.getPeakThreadCount(); long totalCount = threadMXbean.getTotalStartedThreadCount(); list.append("Live: .................... ").append(threadCount).append(" threads").append("\n"); list.append(" Non-Daemon: ......... ") .append(nonDaemonCount) .append(" threads") .append("\n"); list.append(" Daemon: ............. ").append(daemonCount).append(" threads").append("\n"); list.append("Peak: .................... ").append(peakCount).append(" threads").append("\n"); list.append("Total started: ........... ").append(totalCount).append(" threads").append("\n"); list.append("=================================================").append("\n"); for (ThreadInfo info : threadMXbean.dumpAllThreads(lockedMonitors, lockedSynchronizers)) { list.append("Thread #") .append(info.getThreadId()) .append(" (") .append(info.getThreadName()) .append(")") .append("\n"); list.append("=================================================\n"); list.append("\tgetThreadState: ...... ").append(info.getThreadState()).append("\n"); list.append("\tgetWaitedTime: ....... ").append(info.getWaitedTime()).append("\n"); list.append("\tgetBlockedTime: ...... ").append(info.getBlockedTime()).append("\n"); for (MonitorInfo monitorInfo : info.getLockedMonitors()) { list.append("\tLocked monitor: ....... ").append(monitorInfo).append("\n"); list.append("\t\t[") .append(monitorInfo.getLockedStackDepth()) .append(".]: at ") .append(monitorInfo.getLockedStackFrame()) .append("\n"); } for (LockInfo lockInfo : info.getLockedSynchronizers()) { list.append("\tLocked synchronizer: ...").append(lockInfo).append("\n"); } if (stackTrace) { list.append("\tgetStackTace: ..........\n"); for (StackTraceElement trace : info.getStackTrace()) list.append("\t\tat ").append(trace).append("\n"); } list.append("=================================================\n"); } return list; }
public String getThreadDump() { StringBuilder report = new StringBuilder(); report.append("DATE : ").append(dateFormat.format(new Date())).append("\n"); final ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), 100); for (ThreadInfo threadInfo : threadInfos) { report.append(threadInfo); } return report.toString(); }
public void testResolutionUser() { ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); int count = 0; long startTime = threadBean.getCurrentThreadUserTime(); long stopTime = threadBean.getCurrentThreadUserTime(); while (stopTime == startTime) { stopTime = threadBean.getCurrentThreadUserTime(); count++; } System.out.println( "Resolution via UserTime: " + (stopTime - startTime) + "ns in " + count + " iterations."); }
@Override public void query(QueryContext context, String queryString, MetadataCallback callback) { ThreadMXBean bean = ManagementFactory.getThreadMXBean(); ArrayList<ThreadCpuUsage> usages = new ArrayList<ThreadCpuUsage>(); for (long tid : bean.getAllThreadIds()) { long time = bean.getThreadCpuTime(tid); usages.add(new ThreadCpuUsage(tid, time)); } try { Thread.sleep(1000); } catch (InterruptedException e) { } Map<Thread, StackTraceElement[]> stacks = Thread.getAllStackTraces(); for (long tid : bean.getAllThreadIds()) { ThreadCpuUsage usage = find(usages, tid); if (usage != null) usage.secondTime = bean.getThreadCpuTime(tid); } Collections.sort(usages); for (ThreadCpuUsage usage : usages) { long elapsed = usage.secondTime - usage.firstTime; // remove just created thread or sleeping threads (noisy) if (elapsed <= 0) continue; StringBuilder sb = new StringBuilder(); Thread t = findThread(stacks, usage.tid); if (t == null) continue; StackTraceElement[] stack = findStack(stacks, usage.tid); for (StackTraceElement el : stack) { sb.append( String.format( "%s.%s %s\n", el.getClassName(), el.getMethodName(), getFileAndLineNumber(el))); } Map<String, Object> m = new HashMap<String, Object>(); m.put("tid", t.getId()); m.put("name", t.getName()); m.put("state", t.getState().toString()); m.put("priority", t.getPriority()); m.put("usage", elapsed); m.put("stacktrace", sb.toString()); callback.onPush(new Row(m)); } }
/** Constructor */ public ThreadMeasurement() { threadsInfo = null; ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); threadIds = threadBean.getAllThreadIds(); threadsInfo = threadBean.getThreadInfo(threadIds, THREAD_TRACE_DEPTH); threadCount = threadIds.length; threadNames = new String[threadCount]; for (int i = 0; i < threadCount; i++) { if (threadsInfo[i] != null) threadNames[i] = threadsInfo[i].getThreadName(); } } // Constructor end
public static Thread[] getAllThreads() { final ThreadGroup root = getRootThreadGroup(); final ThreadMXBean thbean = ManagementFactory.getThreadMXBean(); int nAlloc = thbean.getThreadCount(); int n = 0; Thread[] threads; do { nAlloc *= 2; threads = new Thread[nAlloc]; n = root.enumerate(threads, true); } while (n == nAlloc); return threads; }
/** * Check if any threads are deadlocked. If any, print the thread dump for those threads. * * @return a deadlock message and the formatted thread dump of the deadlocked threads */ private static String findDeadlock() { ThreadInfo[] tinfos = null; long[] ids = threadMXBean.findDeadlockedThreads(); if (ids != null) { tinfos = threadMXBean.getThreadInfo(threadMXBean.findDeadlockedThreads(), true, true); if (tinfos != null) { StringBuilder sb = new StringBuilder("Deadlock found between the following threads:"); sb.append(CRLF); sb.append(getThreadDump(tinfos)); return sb.toString(); } } return ""; }
public void testTakeCPUTime() { ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); if (!mbean.isThreadCpuTimeEnabled()) { fail("ThreadMXBean CPU time reporting is not enabled"); } long msecMultiplier = 1000 * 1000; long msecGoal = 10; long cpuGoal = msecGoal * msecMultiplier; long beforeCPU = mbean.getCurrentThreadCpuTime(); MyMetricFunctions.takeCPUTime(cpuGoal); long afterCPU = mbean.getCurrentThreadCpuTime(); assertTrue((afterCPU - beforeCPU) > cpuGoal); }
@DwrPermission(admin = true) public ProcessResult getThreadInfo() { synchronized (threadInfos) { ProcessResult result = new ProcessResult(); // All of the last thread ids. Ids are removed from this set as they are processed. If ids // remain, // it means the thread is gone and should be removed from the map. Set<Long> threadIds = new HashSet<>(threadInfos.keySet()); ThreadInfo[] threads = tmxb.getThreadInfo(tmxb.getAllThreadIds(), Integer.MAX_VALUE); List<ThreadInfoBean> beans = new ArrayList<>(); for (ThreadInfo thread : threads) { if (thread == null) continue; ThreadInfoBean bean = threadInfos.get(thread.getThreadId()); if (bean == null) { bean = new ThreadInfoBean(); bean.setId(thread.getThreadId()); bean.setName(thread.getThreadName()); threadInfos.put(bean.getId(), bean); } else threadIds.remove(bean.getId()); bean.setCpuTime(tmxb.getThreadCpuTime(bean.getId())); bean.setState(thread.getThreadState().name()); if (thread.getThreadState() == State.BLOCKED) bean.setState( bean.getState() + " by '" + thread.getLockOwnerName() + "' (" + thread.getLockOwnerId() + ")"); bean.setStackTrace(thread.getStackTrace()); beans.add(bean); } // Remove unreferenced threads for (Long id : threadIds) threadInfos.remove(id); result.addData("threads", beans); return result; } }