-
-
Save logpresso/c7928aefac3f094bef5905c5284eb9cb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import java.io.OutputStream; | |
import java.io.OutputStreamWriter; | |
import java.io.Writer; | |
import java.lang.management.LockInfo; | |
import java.lang.management.ManagementFactory; | |
import java.lang.management.MonitorInfo; | |
import java.lang.management.ThreadInfo; | |
import java.lang.management.ThreadMXBean; | |
public class JstackHelper { | |
private static final String LF; | |
static { | |
LF = System.getProperty("line.separator"); | |
} | |
public static void dump(OutputStream os) throws IOException { | |
String jvmInfo = "Full thread dump " + property("java.vm.name") + "(" + property("java.runtime.version") + " " | |
+ property("java.vm.info") + ")" + LF; | |
String osInfo = property("os.name") + " (version=" + property("os.version") + ", arch=" + property("os.arch") + ")" + LF | |
+ LF; | |
Writer writer = new OutputStreamWriter(os, "utf-8"); | |
writer.write(jvmInfo + LF); | |
writer.write("Operating System" + LF); | |
writer.write("------------------" + LF); | |
writer.write(osInfo); | |
writer.write("Environment Variables" + LF); | |
writer.write("-----------------------" + LF); | |
for (Object key : System.getProperties().keySet()) { | |
writer.write(key + "=" + System.getProperty(key.toString()) + LF); | |
} | |
writer.write(LF); | |
ThreadMXBean bean = ManagementFactory.getThreadMXBean(); | |
long[] tids = bean.getAllThreadIds(); | |
writer.write("Thread dump (total=" + tids.length + ")" + LF); | |
writer.write("------------------------------------------" + LF); | |
for (ThreadInfo t : bean.getThreadInfo(tids, true, true)) { | |
if (t == null) | |
continue; | |
writer.write("\"" + t.getThreadName() + "\" tid=" + t.getThreadId() + ": (state = " + t.getThreadState() + ")" + LF); | |
writer.write(mergeStackTrace(t)); | |
writer.write(LF); | |
} | |
writer.flush(); | |
} | |
private static String property(String name) { | |
String s = System.getProperty(name); | |
if (s == null) | |
return ""; | |
return s; | |
} | |
private static String mergeStackTrace(ThreadInfo t) { | |
StackTraceElement[] stacktrace = t.getStackTrace(); | |
MonitorInfo[] monitors = t.getLockedMonitors(); | |
int idx = 0; | |
StringBuilder sb = new StringBuilder(); | |
for (StackTraceElement el : stacktrace) { | |
LockInfo lock = t.getLockInfo(); | |
String lockOwner = t.getLockOwnerName(); | |
sb.append(String.format(" at %s.%s%s" + LF, el.getClassName(), el.getMethodName(), getFileAndLineNumber(el))); | |
if (idx == 0) { | |
if (el.getClassName().equals("java.lang.Object") && el.getMethodName().equals("wait")) { | |
if (lock != null) { | |
sb.append(String.format(" - waiting on <0x%016x> (%s)" + LF, lock.getIdentityHashCode(), | |
lock.getClassName())); | |
} | |
} else if (lock != null) { | |
if (lockOwner == null) { | |
sb.append(String.format(" - parking to wait for <0x%016x> (%s)" + LF, lock.getIdentityHashCode(), | |
lock.getClassName())); | |
} else { | |
sb.append(String.format(" - waiting to lock <0x%016x> (%s) owned by \"%s\" @%d" + LF, | |
lock.getIdentityHashCode(), lock.getClassName(), lockOwner, t.getLockOwnerId())); | |
} | |
} | |
} | |
for (MonitorInfo monitor : monitors) { | |
if (monitor.getLockedStackDepth() == idx) { | |
sb.append(String.format(" - locked <0x%016x> (%s)\n", monitor.getIdentityHashCode(), monitor.getClassName())); | |
} | |
} | |
idx++; | |
} | |
return sb.toString(); | |
} | |
private static String getFileAndLineNumber(StackTraceElement el) { | |
if (el.getFileName() != null && el.getLineNumber() > 0) | |
return String.format(" (%s:%d)", el.getFileName(), el.getLineNumber()); | |
else if (el.getFileName() != null && el.getLineNumber() <= 0) | |
return String.format(" (%s)", el.getFileName()); | |
else | |
return ""; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Full thread dump Java HotSpot(TM) 64-Bit Server VM(1.8.0_60-b27 mixed mode) | |
Operating System | |
------------------ | |
Windows 10 (version=10.0, arch=amd64) | |
Environment Variables | |
----------------------- | |
(..omitted..) | |
Thread dump (total=5) | |
------------------------------------------ | |
"Attach Listener" tid=5: (state = RUNNABLE) | |
"Signal Dispatcher" tid=4: (state = RUNNABLE) | |
"Finalizer" tid=3: (state = WAITING) | |
at java.lang.Object.wait (Object.java) | |
- waiting on <0x000000002a139a55> (java.lang.ref.ReferenceQueue$Lock) | |
at java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:143) | |
at java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:164) | |
at java.lang.ref.Finalizer$FinalizerThread.run (Finalizer.java:209) | |
"Reference Handler" tid=2: (state = WAITING) | |
at java.lang.Object.wait (Object.java) | |
- waiting on <0x0000000015db9742> (java.lang.ref.Reference$Lock) | |
at java.lang.Object.wait (Object.java:502) | |
at java.lang.ref.Reference$ReferenceHandler.run (Reference.java:157) | |
"main" tid=1: (state = RUNNABLE) | |
at sun.management.ThreadImpl.dumpThreads0 (ThreadImpl.java) | |
at sun.management.ThreadImpl.getThreadInfo (ThreadImpl.java:440) | |
at JstackHelper.dump (JstackHelper.java:52) | |
at Sandbox.main (Sandbox.java:9) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
좋은 정보 감사합니다.
혹시 해당 코드의 라이센스가 어떻게 되는지 알 수 있나요?
회사에서 판매하는 제품에 해당 코드를 사용해도 되는지 알고 싶습니다.