Skip to content

Instantly share code, notes, and snippets.

@chetanmeh
Last active August 29, 2015 14:03
Show Gist options
  • Save chetanmeh/e657f72c52a648b0ce17 to your computer and use it in GitHub Desktop.
Save chetanmeh/e657f72c52a648b0ce17 to your computer and use it in GitHub Desktop.
Script to determine top threads of current Java process
import java.lang.management.ManagementFactory
displayThreadDumpAlso = false
topJavaThreads = "top -b -n 1 -H | grep java"
jstack = "jstack"
maxThreads = 5
pid = myPid()
def dump = threadDump(pid)
def currentCpu = myCpuUsage(pid)
def threads = collectThreads(dump)
def topResult = parseTop(pipeEx(topJavaThreads))
println "PID : $pid"
println "CPU : $currentCpu"
//Sort by CPU higher to lower
def topThreads = new TreeMap(Collections.reverseOrder())
topResult.each { pid, topInfo ->
def threadInfo = threads[pid]
if (threadInfo) {
topThreads[topInfo.cpu] = threadInfo
}
}
def threadCountToShow = Math.min(topThreads.size(), maxThreads)
def threadsToShow = topThreads.entrySet().toList().subList(0, threadCountToShow)
println()
println "Details about top CPU consuming threads"
println()
threadsToShow.each { e ->
println "$e.key :: $e.value.name"
}
println()
println "============================================="
println()
threadsToShow.each { e ->
def trace = e.value.trace
println e.value.line
if (trace) {
trace.each { println " $it" }
} else {
println "<No Trace>"
}
println()
}
println()
println "==================Thread Dump================"
if(displayThreadDumpAlso){
print dump
}
//~--------------------------------------------------------------------------------
def myPid() {
//http://stackoverflow.com/questions/35842/how-can-a-java-program-get-its-own-process-id
String name = ManagementFactory.getRuntimeMXBean().getName();
return Long.parseLong(name.substring(0, name.indexOf('@')));
}
def myCpuUsage(def pid){
parseTopLine(pipeEx("top -bn 1 | grep java | grep \"^\\s*$pid\"")).cpu
}
def parseTop(String output) {
def result = [:]
output.eachLine { line ->
def cols = parseTopLine(line)
result[cols.pid] = cols
}
return result
}
def parseTopLine(String line) {
// PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
// 18205 alec 20 0 7271m 4.5g 27m R 86.4 58.0 173:08.13 java
def cols = line.tokenize().collect { it.trim() }
return [pid: cols[0], cpu: cols[8] as Double, time: cols[10], text: line]
}
def pipeEx(def cmd) {
['sh', '-c', cmd].execute().text
}
def threadDump(def pid) {
return "$jstack -l $pid".execute().text
}
def collectThreads(String dump) {
def traces = Thread.getAllStackTraces()
def threads = [:]
dump.eachLine { line ->
if (line.contains("nid=0x")) {
def info = parseThreadDetails(line)
def entry = traces.find { k, v -> k.name == info.name }
if (entry) {
info.trace = entry.value
}
threads[info.nid] = info
}
}
return threads
}
def parseThreadDetails(String line) {
//"Finalizer" daemon prio=10 tid=0x00007f5fb8142000 nid=0x7911 in Object.wait() [0x00007f5fb4f71000]
def info = (line =~ /^"(.*)".*?nid=0x([\w]+).*/)
return [nid: Long.parseLong(info[0][2], 16) as String, name: info[0][1], line: line]
}

This script extracts the details of top running threads and prints a report from that. This needs to be executed via Felix Script Console from with OSGi Felix Web Console.

  • Works on unix systems only as it relies on top command
  • Reports details for the current java process only
PID : 19605
CPU : 158.9
Details about top CPU consuming threads
98.2 :: pool-9-thread-1
0.0 :: Thread-2998
=============================================
"pool-9-thread-1" prio=10 tid=0x00007f29f4003000 nid=0x4d35 runnable [0x00007f2a51d28000]
org.apache.jackrabbit.oak.plugins.document.Revision$RevisionComparator.compare(Revision.java:527)
org.apache.jackrabbit.oak.plugins.document.Revision$RevisionComparator.compare(Revision.java:398)
java.util.concurrent.ConcurrentSkipListMap$ComparableUsingComparator.compareTo(ConcurrentSkipListMap.java:647)
java.util.concurrent.ConcurrentSkipListMap.findNode(ConcurrentSkipListMap.java:804)
java.util.concurrent.ConcurrentSkipListMap.doGet(ConcurrentSkipListMap.java:828)
java.util.concurrent.ConcurrentSkipListMap.containsKey(ConcurrentSkipListMap.java:1608)
org.apache.jackrabbit.oak.plugins.document.Branch.containsCommit(Branch.java:144)
org.apache.jackrabbit.oak.plugins.document.UnmergedBranches.getBranch(UnmergedBranches.java:120)
org.apache.jackrabbit.oak.plugins.document.NodeDocument.getNodeAtRevision(NodeDocument.java:757)
org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore.readNode(DocumentNodeStore.java:872)
org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore$3.call(DocumentNodeStore.java:661)
org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore$3.call(DocumentNodeStore.java:658)
com.google.common.cache.LocalCache$LocalManualCache$1.load(LocalCache.java:4724)
com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3522)
com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2315)
com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2278)
com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2193)
com.google.common.cache.LocalCache.get(LocalCache.java:3932)
com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:4721)
org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore.getNode(DocumentNodeStore.java:658)
org.apache.jackrabbit.oak.plugins.document.DocumentNodeState.getChildNode(DocumentNodeState.java:163)
org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder.<init>(MemoryNodeBuilder.java:134)
org.apache.jackrabbit.oak.plugins.document.DocumentNodeBuilder.<init>(DocumentNodeBuilder.java:49)
org.apache.jackrabbit.oak.plugins.document.DocumentNodeBuilder.createChildBuilder(DocumentNodeBuilder.java:65)
org.apache.jackrabbit.oak.plugins.document.DocumentNodeBuilder.createChildBuilder(DocumentNodeBuilder.java:38)
org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder.getChildNode(MemoryNodeBuilder.java:316)
org.apache.jackrabbit.oak.core.SecureNodeBuilder.<init>(SecureNodeBuilder.java:117)
org.apache.jackrabbit.oak.core.SecureNodeBuilder.getChildNode(SecureNodeBuilder.java:329)
org.apache.jackrabbit.oak.core.MutableTree.<init>(MutableTree.java:68)
org.apache.jackrabbit.oak.core.MutableTree.getTree(MutableTree.java:322)
org.apache.jackrabbit.oak.core.MutableRoot.getTree(MutableRoot.java:217)
org.apache.jackrabbit.oak.core.MutableRoot.getTree(MutableRoot.java:66)
org.apache.jackrabbit.oak.query.QueryImpl.getTree(QueryImpl.java:862)
org.apache.jackrabbit.oak.query.ast.SelectorImpl.getTree(SelectorImpl.java:488)
org.apache.jackrabbit.oak.query.ast.SelectorImpl.next(SelectorImpl.java:412)
org.apache.jackrabbit.oak.query.QueryImpl$RowIterator.fetchNext(QueryImpl.java:627)
org.apache.jackrabbit.oak.query.QueryImpl$RowIterator.hasNext(QueryImpl.java:647)
com.google.common.collect.Iterators$5.hasNext(Iterators.java:542)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.fetchNext(FilterIterators.java:123)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.hasNext(FilterIterators.java:137)
com.google.common.collect.Iterators$5.hasNext(Iterators.java:542)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.fetchNext(FilterIterators.java:123)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.hasNext(FilterIterators.java:137)
com.google.common.collect.Iterators$5.hasNext(Iterators.java:542)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.fetchNext(FilterIterators.java:123)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.hasNext(FilterIterators.java:137)
com.google.common.collect.Iterators$5.hasNext(Iterators.java:542)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.fetchNext(FilterIterators.java:123)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.hasNext(FilterIterators.java:137)
com.google.common.collect.Iterators$5.hasNext(Iterators.java:542)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.fetchNext(FilterIterators.java:123)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.hasNext(FilterIterators.java:137)
com.google.common.collect.Iterators$5.hasNext(Iterators.java:542)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.fetchNext(FilterIterators.java:123)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.hasNext(FilterIterators.java:137)
com.google.common.collect.Iterators$5.hasNext(Iterators.java:542)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.fetchNext(FilterIterators.java:123)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.hasNext(FilterIterators.java:137)
com.google.common.collect.Iterators$5.hasNext(Iterators.java:542)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.fetchNext(FilterIterators.java:123)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.hasNext(FilterIterators.java:137)
com.google.common.collect.Iterators$5.hasNext(Iterators.java:542)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.fetchNext(FilterIterators.java:123)
org.apache.jackrabbit.oak.query.FilterIterators$DistinctIterator.hasNext(FilterIterators.java:137)
org.apache.jackrabbit.oak.jcr.query.QueryResultImpl$1.fetch(QueryResultImpl.java:108)
org.apache.jackrabbit.oak.jcr.query.QueryResultImpl$1.<init>(QueryResultImpl.java:104)
org.apache.jackrabbit.oak.jcr.query.QueryResultImpl.getRows(QueryResultImpl.java:91)
...
org.quartz.core.JobRunShell.run(JobRunShell.java:207)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:744)
"Thread-2998" daemon prio=10 tid=0x00007f29e001d000 nid=0x2a7 in Object.wait() [0x00007f29c2c4c000]
java.lang.Object.wait(Native Method)
EDU.oswego.cs.dl.util.concurrent.LinkedQueue.poll(Unknown Source)
EDU.oswego.cs.dl.util.concurrent.PooledExecutor.getTask(Unknown Source)
EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Thread.java:744)
==================Thread Dump================
def arg = "crx3"
//Execute top with command path display (c)
//chnage col size so that complete display is seen (export COLUMNS)
//exclude current command (grep -v)
println pipeEx("export COLUMNS=1000;top -cbn 1 | grep java | grep '$arg' | grep -v COLUMNS")
println pipeEx("export COLUMNS=1000;top -cbn 1 -H| grep java | grep '$arg'| grep -v COLUMNS")
def pipeEx(def cmd) {
['sh', '-c', cmd].execute().text
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment