Skip to content

Instantly share code, notes, and snippets.

@jarek-przygodzki
Created November 25, 2012 20:48
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jarek-przygodzki/4145271 to your computer and use it in GitHub Desktop.
Save jarek-przygodzki/4145271 to your computer and use it in GitHub Desktop.
JVM thread dump in Groovy
#!/usr/bin/env groovy
import java.lang.management.*
import javax.management.*
import javax.management.remote.*
import java.text.*
def vmInfo(prop) {
def vmName = prop.getProperty('java.vm.name')
def vmVer = prop.getProperty('java.vm.version')
def vmInfo = prop.getProperty('java.vm.info')
return "Full thread dump $vmName $vmVer $vmInfo"
}
def getProperties(runtimeMxBean) {
def systemProperties = new Properties()
systemProperties.putAll(runtimeMxBean.getSystemProperties())
return systemProperties
}
def jstack(serviceUrl, out) {
jmxUrl = new JMXServiceURL(serviceUrl)
JMXConnector jmxc = JMXConnectorFactory.connect(jmxUrl, null)
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection()
ThreadMXBean threadMXBean = ManagementFactory.newPlatformMXBeanProxy(mbsc,
ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class)
RuntimeMXBean runtimeMxBean = ManagementFactory.newPlatformMXBeanProxy(mbsc,
ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class)
ThreadInfo[] threads = threadMXBean.dumpAllThreads(true, true)
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
out.println df.format(new Date())
out.print vmInfo(getProperties(runtimeMxBean))
out.println ':'
threads.each { t ->
printThreadInfo(t, out)
}
}
def printThreadInfo(ThreadInfo thread, out) {
monitors = thread.lockedMonitors
out.println()
out.println "\"$thread.threadName\" tid=$thread.threadId"
out.println "\tjava.lang.Thread.State: $thread.threadState"
thread.stackTrace.eachWithIndex { st, index ->
lock = thread.lockInfo
lockOwner = thread.lockOwnerName
out.println "\t\tat $st"
if (index == 0) {
if ("java.lang.Object".equals(st.getClassName()) && "wait".equals(st.getMethodName())) {
if (lock != null) {
out.print "\t\t- waiting on "
printLock(lock, out)
out.println()
}
} else if (lock != null) {
if (lockOwner == null) {
out.print "\t\t- parking to wait for "
printLock(lock, out)
out.println()
} else {
out.print "\t\t- waiting to lock "
printLock(lock, out)
out.println " owned by \"$lockOwner\" t@$thread.lockOwnerId"
}
}
}
printMonitors(monitors, index, out)
}
synchronizers = thread.lockedSynchronizers
out.println()
printSynchronizers(synchronizers, out)
}
def printLock(lockInfo, out) {
id = Integer.toHexString(lockInfo.getIdentityHashCode())
className = lockInfo.getClassName()
out.print "<0x$id> (a $className)"
}
def printMonitors(monitors, index, out) {
if(monitors) {
monitors.each { mi ->
if (mi.getLockedStackDepth() == index) {
out.print "\t\t- locked "
printLock(mi, out)
out.println()
}
}
}
}
def printSynchronizers(synchronizers, out) {
out.println "\tLocked ownable synchronizers:"
if (synchronizers == null || synchronizers.length == 0) {
out.println "\t- None"
} else {
synchronizers.each { li ->
out.print "\t- locked "
printLock(li, out);
out.println()
}
}
}
def cli = new CliBuilder(usage: 'jstack -u <jmx url>',
header: 'JVM thread dump in Groovy')
cli.with {
h longOpt: 'help' , args: 0, 'Show usage information and quit'
u longOpt: 'jmxurl', args: 1, argName: 'jmx url', 'JMX service URL'
o longOpt: 'output', args: 1, argName: 'output file', 'Output file'
}
def opts = cli.parse(args)
if(!opts) {
// because the parse failed, the usage will be shown automatically
return
}
if (opts.h || !opts.u) {
cli.usage()
return
}
if(opts.o) {
def sw = new StringWriter()
def pw = new PrintWriter(sw)
jstack(opts.u, pw)
pw.close()
new File(opts.o).withWriter { w ->
w << sw.toString()
}
} else {
jstack(opts.u, System.out)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment