Open Source Debugging for Java 1.4.0

Preview:

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

Twitter

@matthewmccull

Email

matthewm@ambientideas.com

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 McCulloughmatthewm@ambientideas.com

May the debugging force be with you.

Matthew McCulloughmatthewm@ambientideas.com

Thanks in advance for

your completed evals!

Code Examples http://github.com/matthewmccullough

Twitter

@matthewmccull

Email

matthewm@ambientideas.com

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

Recommended