|
18 | 18 | package org.apache.spark.util |
19 | 19 |
|
20 | 20 | import java.io._ |
21 | | -import java.lang.management.{LockInfo, ManagementFactory, MonitorInfo} |
| 21 | +import java.lang.management.{LockInfo, ManagementFactory, MonitorInfo, ThreadInfo} |
22 | 22 | import java.net._ |
23 | 23 | import java.nio.ByteBuffer |
24 | 24 | import java.nio.channels.Channels |
@@ -2131,28 +2131,44 @@ private[spark] object Utils extends Logging { |
2131 | 2131 | // We need to filter out null values here because dumpAllThreads() may return null array |
2132 | 2132 | // elements for threads that are dead / don't exist. |
2133 | 2133 | val threadInfos = ManagementFactory.getThreadMXBean.dumpAllThreads(true, true).filter(_ != null) |
2134 | | - threadInfos.sortBy(_.getThreadId).map { case threadInfo => |
2135 | | - val monitors = threadInfo.getLockedMonitors.map(m => m.getLockedStackFrame -> m).toMap |
2136 | | - val stackTrace = threadInfo.getStackTrace.map { frame => |
2137 | | - monitors.get(frame) match { |
2138 | | - case Some(monitor) => |
2139 | | - monitor.getLockedStackFrame.toString + s" => holding ${monitor.lockString}" |
2140 | | - case None => |
2141 | | - frame.toString |
2142 | | - } |
2143 | | - }.mkString("\n") |
2144 | | - |
2145 | | - // use a set to dedup re-entrant locks that are held at multiple places |
2146 | | - val heldLocks = (threadInfo.getLockedSynchronizers.map(_.lockString) |
2147 | | - ++ threadInfo.getLockedMonitors.map(_.lockString) |
2148 | | - ).toSet |
| 2134 | + threadInfos.sortBy(_.getThreadId).map(threadInfoToThreadStackTrace) |
| 2135 | + } |
2149 | 2136 |
|
2150 | | - ThreadStackTrace(threadInfo.getThreadId, threadInfo.getThreadName, threadInfo.getThreadState, |
2151 | | - stackTrace, if (threadInfo.getLockOwnerId < 0) None else Some(threadInfo.getLockOwnerId), |
2152 | | - Option(threadInfo.getLockInfo).map(_.lockString).getOrElse(""), heldLocks.toSeq) |
| 2137 | + def getThreadDumpForThread(threadId: Long): Option[ThreadStackTrace] = { |
| 2138 | + if (threadId <= 0) { |
| 2139 | + None |
| 2140 | + } else { |
| 2141 | + val threadInfo = Option(ManagementFactory.getThreadMXBean.getThreadInfo(threadId)) |
| 2142 | + threadInfo.map(threadInfoToThreadStackTrace) |
2153 | 2143 | } |
2154 | 2144 | } |
2155 | 2145 |
|
| 2146 | + private def threadInfoToThreadStackTrace(threadInfo: ThreadInfo): ThreadStackTrace = { |
| 2147 | + val monitors = threadInfo.getLockedMonitors.map(m => m.getLockedStackFrame -> m).toMap |
| 2148 | + val stackTrace = threadInfo.getStackTrace.map { frame => |
| 2149 | + monitors.get(frame) match { |
| 2150 | + case Some(monitor) => |
| 2151 | + monitor.getLockedStackFrame.toString + s" => holding ${monitor.lockString}" |
| 2152 | + case None => |
| 2153 | + frame.toString |
| 2154 | + } |
| 2155 | + }.mkString("\n") |
| 2156 | + |
| 2157 | + // use a set to dedup re-entrant locks that are held at multiple places |
| 2158 | + val heldLocks = |
| 2159 | + (threadInfo.getLockedSynchronizers ++ threadInfo.getLockedMonitors).map(_.lockString).toSet |
| 2160 | + |
| 2161 | + ThreadStackTrace( |
| 2162 | + threadId = threadInfo.getThreadId, |
| 2163 | + threadName = threadInfo.getThreadName, |
| 2164 | + threadState = threadInfo.getThreadState, |
| 2165 | + stackTrace = stackTrace, |
| 2166 | + blockedByThreadId = |
| 2167 | + if (threadInfo.getLockOwnerId < 0) None else Some(threadInfo.getLockOwnerId), |
| 2168 | + blockedByLock = Option(threadInfo.getLockInfo).map(_.lockString).getOrElse(""), |
| 2169 | + holdingLocks = heldLocks.toSeq) |
| 2170 | + } |
| 2171 | + |
2156 | 2172 | /** |
2157 | 2173 | * Convert all spark properties set in the given SparkConf to a sequence of java options. |
2158 | 2174 | */ |
|
0 commit comments