Upload
matthew-mccullough
View
3.774
Download
2
Tags:
Embed Size (px)
DESCRIPTION
Open Source Debugging for Java given at the Dallas MUG
Citation preview
by Matthew McCullough of Ambient Ideas, LLC
Java Debugging Tools
Open Source
Code Examples http://github.com/matthewmccullough
@matthewmccull
Blog
http://www.ambientideas.com/blog sidebar has my social networking profile links
http://delicious.com/matthew.mccullough/opensource+debugging
Not
Instead
VisualVM
Eclipse MAT
jstack
jhatjmap
jstat
jstatdTOD
TPTP
jps
Hotspot JVMs
jps process list
What JVM options did we use when we started up the app
server?
jps
jps -l
◀Sho
w fu
ll pac
kage n
ame
jps -l -v
◀Sho
w fu
ll pac
kage n
ame
◀Sho
w JV
M arg
ument
s
jps -l -v -m
◀Sho
w fu
ll pac
kage n
ame
◀Sho
w JV
M arg
ument
s
◀Sho
w ma
in() a
rgume
nts
VIDEO JPS
only local?
jps 10.15.25.32
How?
Run jstatd daemon
Allow-all policy
jstatd -J-Djava.security.policy=allowall.pol
◀You
r Poli
cy
grant codebase "file:${java.home}/../lib/tools.jar" { permission java.security.AllPermission;};
grant codebase "file:${java.home}/../lib/tools.jar" { permission java.net.SocketPermission "<YourDesktopHostnameOrIP>:1099", "accept, connect, listen, resolve";};
let’s start up the jstatd daemon
VIDEO JSTATD
jps 10.15.25.32
let’s run JPS from Windows
across the network to a Mac
VIDEO JPS REMOTE
jstat process info
jstat -gcutil <pid>
◀Sho
w gar
bage c
ollec
tion
jstat -gcutil <pid> 500 999◀m
s betw
een sa
mples
◀repe
tition
s
jstat -gcutil -h5 <pid> 500 999
◀Sho
w he
ader e
very X
lines
VIDEO JSTAT REMOTE
jstack stack dumps
jstack <pid>
jstack -F <pid>
jstack -l <pid>◀Verb
ose l
ock i
nfo
Direct this output to a file with a tdump extension
Use TDA on VisualVM to analyze it
javap class file disassembler
We added a new method to a class.
Is it on theserver-deployed copy
of the app?
javap classfile
javap -v classfile
◀Verb
ose
major version: 48 = Java 1.4major version: 49 = Java 5major version: 50 = Java 6
javap -s classfile◀Inte
rnal t
ype si
gnatu
res
javap -private classfile
◀Sho
w Priva
te me
thod
s
Survey
StackOverflow.com
Your favoriteOpen Source Debugging Tool?
VisualVM
❸
Eclipse
❷
System.out.println(brokenobj);
❶
System.out.println(brokenobj);System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
System.out.println(brokenobj);
I’ve got the only tool I need
jmap memory maps
jmap histogram
jmap -histo <pid>
jmap -histo:live <pid>
jmap heap dump
jmap -dump:file=myfile.hprof <pid>
java -XX:+HeapDumpOnOutOfMemoryError MyApp
jinfo -flag +HeapDumpOnOutMemoryError <pid>
OutOfMemoryErrorDrive in to office!
jhat heap analysis
jhat -J-Xmx512m <yourdump.hprof>
jhat -J-Xmx512m <yourdump.hprof>
jhat -J-Xmx512m <yourdump.hprof>
http://localhost:7000
OQL
select z from java.lang.String z
select z from java.lang.String z where z.count >= 50
http://blogs.sun.com/sundararajan/date/200509
eclipse memory analyzerM.A.T.
PurposeInvestigate memory usage.
Useful forVisualizing memory footprint.
Finding memory leaks.
Querying through (OQL) allocated memory.
Discovering heavy memory allocation sources.
EclipseMemoryAnalyzer
GotchaDoesn’t create heap dumps, just analyzes.Available as a plugin or standalone RCP app.
EclipseMemoryAnalyzer
java.lang.String
java.util.HashMap
char[]char[]char[]char[]char[]
java.lang.Stringjava.lang.String
char[]char[]char[]char[]char[]
char[]char[]char[]char[]char[]
Shallow Heap
java.lang.String
java.util.HashMap
char[]char[]char[]char[]char[]
java.lang.Stringjava.lang.String
char[]char[]char[]char[]char[]
char[]char[]char[]char[]char[]
Retained Heap
java.lang.String
java.util.HashMap
char[]char[]char[]char[]char[]
java.lang.Stringjava.lang.String
char[]char[]char[]char[]char[]
char[]char[]char[]char[]char[]
Load a heap dump in MAT
VIDEO ECLIPSE MAT
Run some OQL on it
VIDEO ECLIPSE MAT OQL
btrace
Can you put a few debugging
“sysouts” into that running production
app?
BTrace Tracing
BTrace Tracing
Production-timeOperates on deployed codeUses debugging hooks to re-deploy class filesRuntime injection of tracing statements
BTrace Tracing
CodeTracing scripts written in Java.Limited to a catalog of static methods.Compiled at design time or tracing time.
Unsafe mode
BTrace Tracing
CodeTracing scripts written in Java.Limited to a catalog of static methods.Compiled at design time or tracing time.
Unsafe mode
BTrace Tracing
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.AnyType;import java.lang.management.MemoryUsage;import java.util.concurrent.atomic.AtomicInteger;import java.util.Map;
@BTrace public class TraceAllMethodCalls { /** * METHOD CALL TRACEPOINT. */ @OnMethod( clazz="com.ambientideas.HelloWorldJava", method="print", location=@Location(value=Kind.CALL, clazz="/.*/", method="/.*/") ) public static void m(AnyType[] args) { //System.out.println("Hello"); println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } @OnMethod( clazz="/.*/", method="println" ) public static void m2(AnyType[] args) { println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } /** * ONEXIT TRACEPOINT. CALLED WHEN A BTRACE METHOD CALLS EXIT(INT). */ @OnExit public static void onexit(int code) { println("****** THE BTRACE PROGRAM IS EXITING."); }
/** * LOW MEMORY TRACE POINT. */ @OnLowMemory( pool = "Tenured Gen", threshold=58720250 ) public static void onLowMem(MemoryUsage mu) { println("******"); println(mu); } /** * MEMORY HISTOGRAM TRACE POINT. */ private static Map<String, AtomicInteger> histo = newHashMap();
@OnTimer(4000) public static void print() { if (size(histo) != 0) { printNumberMap(strcat("******", "Component Histogram"), histo); } }}
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.AnyType;import java.lang.management.MemoryUsage;import java.util.concurrent.atomic.AtomicInteger;import java.util.Map;
@BTrace public class TraceAllMethodCalls { /** * METHOD CALL TRACEPOINT. */ @OnMethod( clazz="com.ambientideas.HelloWorldJava", method="print", location=@Location(value=Kind.CALL, clazz="/.*/", method="/.*/") ) public static void m(AnyType[] args) { //System.out.println("Hello"); println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } @OnMethod( clazz="/.*/", method="println" ) public static void m2(AnyType[] args) { println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } /** * ONEXIT TRACEPOINT. CALLED WHEN A BTRACE METHOD CALLS EXIT(INT). */ @OnExit public static void onexit(int code) { println("****** THE BTRACE PROGRAM IS EXITING."); }
/** * LOW MEMORY TRACE POINT. */ @OnLowMemory( pool = "Tenured Gen", threshold=58720250 ) public static void onLowMem(MemoryUsage mu) { println("******"); println(mu); } /** * MEMORY HISTOGRAM TRACE POINT. */ private static Map<String, AtomicInteger> histo = newHashMap();
@OnTimer(4000) public static void print() { if (size(histo) != 0) { printNumberMap(strcat("******", "Component Histogram"), histo); } }}
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.AnyType;import java.lang.management.MemoryUsage;import java.util.concurrent.atomic.AtomicInteger;import java.util.Map;
@BTrace public class TraceAllMethodCalls { /** * METHOD CALL TRACEPOINT. */ @OnMethod( clazz="com.ambientideas.HelloWorldJava", method="print", location=@Location(value=Kind.CALL, clazz="/.*/", method="/.*/") ) public static void m(AnyType[] args) { //System.out.println("Hello"); println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } @OnMethod( clazz="/.*/", method="println" ) public static void m2(AnyType[] args) { println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } /** * ONEXIT TRACEPOINT. CALLED WHEN A BTRACE METHOD CALLS EXIT(INT). */ @OnExit public static void onexit(int code) { println("****** THE BTRACE PROGRAM IS EXITING."); }
/** * LOW MEMORY TRACE POINT. */ @OnLowMemory( pool = "Tenured Gen", threshold=58720250 ) public static void onLowMem(MemoryUsage mu) { println("******"); println(mu); } /** * MEMORY HISTOGRAM TRACE POINT. */ private static Map<String, AtomicInteger> histo = newHashMap();
@OnTimer(4000) public static void print() { if (size(histo) != 0) { printNumberMap(strcat("******", "Component Histogram"), histo); } }}
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.AnyType;import java.lang.management.MemoryUsage;import java.util.concurrent.atomic.AtomicInteger;import java.util.Map;
@BTrace public class TraceAllMethodCalls { /** * METHOD CALL TRACEPOINT. */ @OnMethod( clazz="com.ambientideas.HelloWorldJava", method="print", location=@Location(value=Kind.CALL, clazz="/.*/", method="/.*/") ) public static void m(AnyType[] args) { //System.out.println("Hello"); println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } @OnMethod( clazz="/.*/", method="println" ) public static void m2(AnyType[] args) { println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } /** * ONEXIT TRACEPOINT. CALLED WHEN A BTRACE METHOD CALLS EXIT(INT). */ @OnExit public static void onexit(int code) { println("****** THE BTRACE PROGRAM IS EXITING."); }
/** * LOW MEMORY TRACE POINT. */ @OnLowMemory( pool = "Tenured Gen", threshold=58720250 ) public static void onLowMem(MemoryUsage mu) { println("******"); println(mu); } /** * MEMORY HISTOGRAM TRACE POINT. */ private static Map<String, AtomicInteger> histo = newHashMap();
@OnTimer(4000) public static void print() { if (size(histo) != 0) { printNumberMap(strcat("******", "Component Histogram"), histo); } }}
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.AnyType;import java.lang.management.MemoryUsage;import java.util.concurrent.atomic.AtomicInteger;import java.util.Map;
@BTrace public class TraceAllMethodCalls { /** * METHOD CALL TRACEPOINT. */ @OnMethod( clazz="com.ambientideas.HelloWorldJava", method="print", location=@Location(value=Kind.CALL, clazz="/.*/", method="/.*/") ) public static void m(AnyType[] args) { //System.out.println("Hello"); println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } @OnMethod( clazz="/.*/", method="println" ) public static void m2(AnyType[] args) { println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } /** * ONEXIT TRACEPOINT. CALLED WHEN A BTRACE METHOD CALLS EXIT(INT). */ @OnExit public static void onexit(int code) { println("****** THE BTRACE PROGRAM IS EXITING."); }
/** * LOW MEMORY TRACE POINT. */ @OnLowMemory( pool = "Tenured Gen", threshold=58720250 ) public static void onLowMem(MemoryUsage mu) { println("******"); println(mu); } /** * MEMORY HISTOGRAM TRACE POINT. */ private static Map<String, AtomicInteger> histo = newHashMap();
@OnTimer(4000) public static void print() { if (size(histo) != 0) { printNumberMap(strcat("******", "Component Histogram"), histo); } }}
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.AnyType;import java.lang.management.MemoryUsage;import java.util.concurrent.atomic.AtomicInteger;import java.util.Map;
@BTrace public class TraceAllMethodCalls { /** * METHOD CALL TRACEPOINT. */ @OnMethod( clazz="com.ambientideas.HelloWorldJava", method="print", location=@Location(value=Kind.CALL, clazz="/.*/", method="/.*/") ) public static void m(AnyType[] args) { //System.out.println("Hello"); println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } @OnMethod( clazz="/.*/", method="println" ) public static void m2(AnyType[] args) { println(strcat("****** WE'VE ENTERED A METHOD ON CLASS: ", name(probeClass()))); println(strcat("****** WE'VE ENTERED METHOD: ", probeMethod())); } /** * ONEXIT TRACEPOINT. CALLED WHEN A BTRACE METHOD CALLS EXIT(INT). */ @OnExit public static void onexit(int code) { println("****** THE BTRACE PROGRAM IS EXITING."); }
/** * LOW MEMORY TRACE POINT. */ @OnLowMemory( pool = "Tenured Gen", threshold=58720250 ) public static void onLowMem(MemoryUsage mu) { println("******"); println(mu); } /** * MEMORY HISTOGRAM TRACE POINT. */ private static Map<String, AtomicInteger> histo = newHashMap();
@OnTimer(4000) public static void print() { if (size(histo) != 0) { printNumberMap(strcat("******", "Component Histogram"), histo); } }}
visualvm
Useful for‣ Discovering the GC cycles of your app.
‣ Finding the largest memory usage culprits.
‣ Diffing memory snapshots.
‣ Injecting btrace code.
‣ Snapping heapdumps.
GotchaDownload version 1.2 even if your JDK includes 1.0.Standalone version always ahead of JVM version.
VisualVM in action
BTrace in action
omniscient debuggers
Luke, you candestroy the bug!
He has foreseen this.
It is your destiny.
TOD(by Guillaume Pothier)
TOD✴ Eclipse-integrated omniscient debugger
✴ observe all memory changes
✴ execute once, review infinitely
✴ rewind and step through call stacks, loops
✴ Windows-only (DLL)
VIDEO TOD
comprehension tools
Goal:Comprehend the application runtime call sequence better.
amida
amidahttp://sel.ist.osaka-u.ac.jp/~ishio/amida/
jtracert
jtracerthttp://code.google.com/p/jtracert/
Eclipse TPTP
Eclipse TPTP
✴ profile an application’s performance
✴ render call sequence diagrams
✴ almost ready for Mac OS
VIDEO TPTP
decompiling tools
cavaj
JODE
JD-Eclipse
System.out.println()
ancient weapons are no match...
bring a better weapon to the fight
if a bug
strikesyoudown...
You work the weekend solving it.
Matthew [email protected]
May the debugging force be with you.
Matthew [email protected]
Thanks in advance for
your completed evals!
Code Examples http://github.com/matthewmccullough
@matthewmccull
Blog
http://www.ambientideas.com/blog sidebar has my social networking profile links
Eclipse Memory Analyzerhttp://www.eclipse.org/mat/
VisualVMhttps://visualvm.dev.java.net/
GCHistohttps://gchisto.dev.java.net/
BTracehttps://btrace.dev.java.net/
DTrace, XRay, Instrumentshttp://en.wikipedia.org/wiki/DTrace
Resources
TODhttp://pleiad.cl/tod/
JTracerthttp://code.google.com/p/jtracert/
Amidahttp://sel.ist.osaka-u.ac.jp/~ishio/amida/
TPTPhttp://www.eclipse.org/tptp/
JD-Eclipsehttp://java.decompiler.free.fr/
Resources
‣ http://www.ambientideasphotography.com‣ http://upload.wikimedia.org/wikipedia/commons/a/a4/
BernardMadoff.jpg‣ http://flickr.com/photos/triller/2226679393/‣ http://flickr.com/photos/ektogamat/2687444500/‣ http://flickr.com/photos/bfionline/2380398799/‣ http://flickr.com/photos/symphoney/76513801/‣ http://flickr.com/photos/foxypar4/2124673642/‣ http://flickr.com/photos/morberg/3146874095/‣ http://flickr.com/photos/triller/2226679393/
Image Credits