Download presentation
1
Java Debugging & Profiling Techniques
Ethan Henry KL Group
2
Overview This session will touch on three major topics: Debugging
and Profiling plus Memory Leaks in Java
3
Debugging What’s debugging? If you don’t already know…
Debugging is the process of finding errors in your software, regardless of what kind of errors they are
4
Types of Errors Program errors can be lumped into one of three broad categories: syntactic errors static errors dynamic errors Syntactic errors are the easiest to find, dynamic errors are the most difficult
5
Syntactic Errors A syntactic error is one in which the program is ill-formed by the standard of the programming language e.g. a keyword is misspelled Syntactic errors are trivial to detect and correct the compiler does the detection for you which is one reason compiled languages are so popular
6
Static Errors Static errors are ones in which the program is syntactically correct but semantically incorrect For example, substituting a “>” for a “<” Static errors can be very difficult to detect but are usually quite obvious Java’s exception mechanism helps deal with these types of errors
7
Dynamic Errors The dynamic error is the most insidious kind of errors
Dynamic errors occur in code which is both semantically and syntactically correct but where implicit assumptions have been violated The prevention of dynamic errors is a major focus of software engineering
8
Dynamic Errors An example of a dynamic error:
the most dramatic example I could find The Ariane 5 crash on June 4, 1996 was due to a reuse error reuse of an inertial reference system software component caused a 64-bit integer to be incorrectly converted into a 16-bit unsigned integer, causing an exception that went uncaught and crashed the guidance system
9
Debugging Techniques Debugging is an art as old as programming is, so there are a lot of approaches to it For Java, we can divide debugging techniques into two categories: “Classic” Java-specific
10
Classic Debugging Techniques
print statements assert
11
Jurassic Debugging println statements
System.out.println connected to the standard output stream System.err.println connected to the standard error stream both are instances of java.io.PrintStream helps with static & dynamic errors difficult to deal with in general
12
toString() The one very useful thing about using println to debug is that every object has a toString() method inherited from Java.lang.Object This means that you can always do things like this: Frame f = new Frame(“Main App”); System.out.println(“The frame info is “+f);
13
toString() By default, toString() just prints out an object identifier, so you should override it in your own classes Tip: The first thing you should do in a toString method is create a StringBuffer to hold the data you’re printing
14
Using println How can you make debugging statements easier to deal with? Conditional code via if via a pre-processor a debugging class
15
Using println If use an expression that’s constant at compile time, if statements act like conditional code and will be evaluated at compile time static final boolean DEBUG = true; // or false … if(DEBUG) { System.out.println(“Some message”); }
16
Using println Another option is to use an actual pre-processor, like in C/C++ cpp, perl, m4, tcl - any general scripting language should work This is more complex, but is marginal extra work in a large project Advantage over using if: you can completely strip out the debugging code if you want
17
Using println Another technique is to use a class that logs errors
typically a singleton For example:
18
import java.io.*; public final class Log { private static Log log; private PrintStream stream; private boolean printing; private Log() { stream = System.out; printing = true; } static { log = new Log(); public static Log getLog() { return log;
19
public void setPrinting(boolean b) {
} public void setStream(OutputStream os) { if(os instanceof PrintStream) stream = (PrintStream)os; else stream = new PrintStream(os); public void println(String msg) { if(printing) stream.println(msg); public void print(String msg) { stream.print(msg);
20
Assert Assert is a classic C & C++ programming construct
Assert statements are used to verify various conditions in program code Very useful for detecting dynamic errors For example: public int doThing(int x) { Assert.assert(x > 0); // do some things... }
21
Assert While the C assert stops the program, a Java assert would be better off doing something less intrusive, like throwing a RuntimeException There is an example of a full assert package (JContracts) at: There’s a JSR on the subject as well:
22
A sample assert class public final class Assert {
// change to false if you want to disable assertions private final static boolean ENFORCE = true; public static void assert(boolean b) { if(ENFORCE && (b == false)) throw new RuntimeException("assertion violated"); }
23
Java-Specific Techniques
Exception Handling Reading Exception Messages Thread Dumps
24
Exception Handling An exception is “thrown” when some unexpected condition occurs at runtime Only instances of java.lang.Throwable (or a subclass) can be thrown by the throw statement Throwable has two subclasses: java.lang.Error java.lang.Exception
25
Errors Error objects are thrown by the virtual machine or Java library to indicate a serious problem Most applications shouldn’t try to catch or throw an Error object The predefined errors are:
26
Errors java.awt.AWTError java.lang.LinkageError
java.lang.ClassCircularityError java.lang.ClassFormatError java.lang.ExceptionInInitializerError java.lang.IncompatibleClassChangeError java.lang.AbstractMethodError java.lang.IllegalAccessError java.lang.InstantiationError java.lang.NoSuchFieldError java.lang.NoSuchMethodError java.lang.NoClassDefFoundError java.lang.UnsatisfiedLinkError java.lang.VerifyError java.lang.ThreadDeath java.lang.VirtualMachineError java.lang.InternalError java.lang.OutOfMemoryError java.lang.StackOverflowError java.lang.UnknownError
27
Exceptions An exception indicates some sort of problem that a typical application might want to deal with There are two types of exceptions: checked exceptions unchecked exceptions
28
Checked Exceptions Direct subclasses of java.lang.Exception represent exceptions that the developer must deal with These exceptions can only be thrown if declared in the throws clause of the method Any code calling a method that throws a regular exception must catch it and deal with it
29
Checked Exceptions Some examples of checked exceptions are:
java.lang.ClassNotFoundException thrown by Class.forName() java.io.IOException thrown by many I/O operations java.lang.IllegalAccessException thrown by Class.newInstance() java.lang.InterruptedException thrown by sleep and wait
30
Unchecked Exceptions Unchecked exceptions need not be declared in the throws clause of a method and do not need to be caught These are exceptions that are too frequent to check for every time Unchecked exceptions are derived from java.lang.RuntimeException instead of java.lang.Exception RuntimeException is derived from Exception though
31
Unchecked Exceptions Some example of unchecked exceptions:
java.lang.ArithmeticException java.lang.ClassCastException java.lang.IllegalArgumentException java.lang.NumberFormatException java.lang.ArrayIndexOutOfBoundsException java.lang.StringIndexOutOfBoundsException java.lang.NegativeArraySizeException java.lang.NullPointerException
32
Handling Exceptions Exceptions are dealt with via the throw, try, catch and finally keywords The code that encounters a problem creates an exception by instantiating some exception object and throwing it throw new SomeBadException(“some message”);
33
Handling Exceptions The exception then unwinds the stack of the thread it was thrown in, looking for a try block If there is a catch associated with the try block that matches the type of the exception, the catch block is executed After the catch block executes (or if no exception was thrown) the finally block associated with the try block is executed
34
Handling Exceptions If no handler is found, the current thread’s ThreadGroup’s uncaughtException(Thread,Throwable) method is called if there is a parent ThreadGroup, pass it the exception otherwise print the exception stack trace to System.err
35
Handling Exceptions import java.io.IOException;
public class Exception { public static void main(String args[]) { try { foo(args[0]); System.out.println("whew"); } catch(IOException e) { System.out.println("doh!"); finally { System.out.println("finally..."); System.out.println("done!");
36
Handling Exceptions public static void foo(String s) throws IOException { if(s.equals("checked")) { throw new IOException("Checked"); } else if(s.equals("unchecked")) { throw new RuntimeException("Unchecked"); System.out.println("No exception");
37
Reading Exception Messages
A typical exception stack trace looks something like this: from a modified version of the ‘Fractal’ example that comes with the JDK java.lang.NullPointerException at ContextLSystem.<init>(CLSFractal.java:319) at CLSFractal.init(CLSFractal.java:66) at sun.applet.AppletPanel.run(AppletPanel.java:287) at java.lang.Thread.run(Thread.java:474)
38
Reading Exception Messages
Information shown: the type of exception java.lang.NullPointerException the class & method in which the exception was thrown at ContextLSystem.<init>(CLSFractal.java:319) the full stack trace for the thread executing the code at that point at CLSFractal.init(CLSFractal.java:66) at sun.applet.AppletPanel.run(AppletPanel.java:287) at java.lang.Thread.run(Thread.java:474) Note that line numbers are not shown if a JIT is being used
39
Reading Exception Messages
There are two special methods that aren’t identified by their human-readable names: <init> a constructor <clinit> the static “class constructor” code block
40
The “Magic Thread Dump Key”
Windows: Ctrl-Break Solaris: Ctrl-\ or kill -QUIT [pid] A sample thread dump How to read a thread dump Diagnosing deadlock
41
A Sample Thread Dump From a sample application:
Full thread dump Classic VM (JDK-1.2-V, native threads): "Thread-0" (TID:0x1915a28, sys_thread_t:0x8ebd60, state:CW, native ID:0x113) prio=5 "AWT-Windows" (TID:0x1916ce0, sys_thread_t:0x8a6410, state:R, native ID:0x10a) prio=5 at sun.awt.windows.WToolkit.eventLoop(Native Method) at sun.awt.windows.WToolkit.run(WToolkit.java:134) at java.lang.Thread.run(Thread.java:479) "SunToolkit.PostEventQueue-0" (TID:0x1916e10, sys_thread_t:0x8a5b70, state:CW, native ID:0x103) prio=5 at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Compiled Code) at sun.awt.PostEventQueue.run(SunToolkit.java:363) "AWT-EventQueue-0" (TID:0x1916de0, sys_thread_t:0x8a3680, state:CW, native ID:0x10d) prio=6 at java.awt.EventQueue.getNextEvent(EventQueue.java:179) at java.awt.EventDispatchThread.run(EventDispatchThread.java:67) "Finalizer" (TID:0x18f9320, sys_thread_t:0x8209d0, state:CW, native ID:0x116) prio=8 at java.lang.ref.ReferenceQueue.remove(Compiled Code) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:174)
42
A Sample Thread Dump "Reference Handler" (TID:0x18f93b0, sys_thread_t:0x81fdc0, state:CW, native ID:0x10f) prio=10 at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Compiled Code) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:114) "Signal dispatcher" (TID:0x18f93e0, sys_thread_t:0x81f560, state:R, native ID:0x117) prio=5 Monitor Cache Dump: <unowned> Waiting to be notified: "SunToolkit.PostEventQueue-0" (0x8a5b70) <unowned> "AWT-EventQueue-0" (0x8a3680) <unowned> "Finalizer" (0x8209d0) <unowned> "Reference Handler" (0x81fdc0)
43
A Sample Thread Dump Registered Monitor Dump:
Invoker change lock: <unowned> utf8 hash table: <unowned> JNI pinning lock: <unowned> JNI global reference lock: <unowned> BinClass lock: <unowned> Class linking lock: <unowned> System class loader lock: <unowned> Code rewrite lock: <unowned> Heap lock: <unowned> Monitor cache lock: owner "Signal dispatcher" (0x81f560) 1 entry Thread queue lock: owner "Signal dispatcher" (0x81f560) 1 entry Waiting to be notified: "Thread-0" (0x8ebd60) Monitor registry: owner "Signal dispatcher" (0x81f560) 1 entry
44
How to Read a Thread Dump
The thread dump contains the following information: a listing of all the threads running in the VM including a full stack dump if available plus the native thread id, priority and current thread state a list of all monitors that have been created including the current owner and the number of threads waiting for that monitor to be released a list of all “special” monitors these are used by the VM internally
45
Thread States Each thread has a state associated with it:
R Running or runnable thread S Suspended thread CW Thread waiting on a condition variable MW Thread waiting on a monitor lock MS Thread suspended waiting on a monitor lock You should never see a thread in the ‘MS’ state if you do, there’s a good chance it’s a VM bug
46
More on Thread Dumps The JDC has a very nice, detailed description of what each element in the thread dump is: This includes details on what each of the internal monitors are for and more It’s for JDK 1.1, but should be helpful for JDK 1.2 as well
47
Other Magic Keys Related to the “Magic Thread Dump” key is the “Magic AWT Dump” key Ctrl+Shift+F1 the code for this is hidden away inside java.awt.Window of all places Magic Netscape Console Keys hit ? in the Navigator Java console to get the list of commands
48
Interactive Debuggers
Free: jdb JBuilder Foundation (IDE) NetBeans Developer/Forte for Java (IDE) Commercial: Metamata Debug Karmira BugSeeker
49
JDK 1.0/1.1 Debugging API The Java VMs in JDK 1.0 and JDK 1.1 support a basic remote debugging API A remote agent is built into the Java VM which can be accessed over a socket via the RemoteDebugger class Most of this API has never been formally published
50
Instance of RemoteDebugger
JDK 1.0/1.1 Debugging API The basic debugger architecture: h Java Interpreter Java VM Agent Request Reply Instance of RemoteDebugger Java Debugging Client
51
JDK 1.0/1.1 Debugging API To use the debugging agent, start the JVM with the -debug command line option this may require the use of java_g On the debug client side, create an instance of the RemoteDebugger class which can be used to: list all classes in the target JVM obtain a specific RemoteClass monitor memory usage and initiate GC
52
JDK 1.0/1.1 Debugging API The RemoteClass class can be used to:
get all the fields & methods in the class set breakpoints in methods All of these classes are in the sun.tools.debug package source for this package is not included with the JDK although it is included with the VM source
53
JDK 1.0/1.1 Debugging API The classes in sun.tools.debug are:
RemoteValue RemoteBoolean RemoteByte RemoteChar RemoteDouble RemoteFloat RemoteInt RemoteLong RemoteShort RemoteObject RemoteArray RemoteClass RemoteString RemoteThread RemoteThreadGroup RemoteField RemoteStackVariable RemoteDebugger DebuggerCallback
54
JDK 1.2 Debugging API JDK 1.2 has a new, improved debugging API that is fully documented The JPDA API has been broken down into three isolated parts: JVMDI: Java Virtual Machine Debug Interface. A low-level native interface. Defines the services a VM must provide for debugging.
55
JDK 1.2 Debugging API JDWP: Java Debug Wire Protocol
Defines the format of information and requests transferred between the debugging process and the debugger front-end The transport mechanism is unspecified could be a socket, shared memory, etc JDI: Java Debug Interface A high-level 100% Pure Java interface, including support for remote debugging For use on the client/debugger side
56
communication channel
JDK 1.2 Debugging API VM back-end JVMDI debuggee communication channel JDWP front-end JDI debugger UI
57
Profiling What is Profiling? What Profiling Tells You
What Profiling Is Not Manual Profiling Profiling Techniques Overview Insertion Sampling Instrumented VM
58
What is Profiling? Profiling is measuring an application, specifically: where is the time being spent? This is “classical” profiling which method takes the most time? which method is called the most? how is memory being used? what kind of objects are being created? this in especially applicable in OO, GC’ed environments
59
What Profiling Tells You
Basic information: How much time is spent in each method? (“flat” profiling) How many objects of each type are allocated?
60
What Profiling Tells You
Beyond the basics: Program flow (“hierarchical” profiling) do calls to method A cause method B to take too much time? Per-line information which line(s) in a given method are the most expensive? Which methods created which objects? Visualization aspects Is it easy to use the profiler to get to the information you’re interested in?
61
What Profiling Is Not Profiling is measuring performance statistics on your particular application regardless of the underlying platform Benchmarking is measuring the performance of a particular platform not a specific application Optimization is an automatic technique that applies generic enhancements to speed up code regardless of the application or platform
62
Optimization Even though optimization isn’t always enough, it’s a good place to start Java is designed to be optimized by the JVM, not by the compiler even though there are optimizing compilers JIT compilers help Sun’s next-generation JVM, HotSpot, offers: generational garbage collection improved, profiling native compiler
63
Manual Profiling You don’t absolutely need to have a profiling tool to profile your code… you could build your own profiling tool see Dr. Dobb’s Journal, March 1998 Or Dr. Dobbs, Sept. 1999 use very simple code-insertion techniques System.out.println(System.getCurrentTimeMillis());
64
Profiling Techniques Overview
Commercial profilers use one of three techniques for profiling programs: insertion sampling instrumented virtual machine Why is it important to understand how a profiler works? each different technique has its own pros & cons different profilers may give different results
65
Insertion Multiple flavours: Source code insertion
profiling code goes in with the source easy to do Object code insertion profiling code goes into the .o (C++) or .class (Java) files can be done statically or dynamically hard to do modified class loader
66
Insertion Pros & Cons Insertion Pros: Insertion Cons:
can be used across a variety of platforms accurate (in some ways) can’t easily do memory profiling Insertion Cons: requires recompilation or relinking of the app profiling code may affect performance difficult to calculate exact impact
67
Sampling In sampling, the processor or VM is monitored and at regular intervals an interrupt executes and saves a “snapshot” of the processor state This data is then compared with the program’s layout in memory to get an idea of where the program was at each sample
68
Sampling Pros & Cons Sampling Pros: Sampling Cons:
no modification of app is necessary Sampling Cons: a definite time/accuracy trade-off a high sample rate is accurate, but takes a lot of time more…
69
Sampling Pros & Cons Sampling Cons:
very small methods will almost always be missed if a small method is called frequently and you have are unlucky, small but expensive methods may never show up sampling cannot easily monitor memory usage
70
Instrumented VM Another way to collect information is to instrument the Java VM Using this technique each and every VM instruction can be monitored highly accurate
71
Instrumented VM Pros&Cons
The most accurate technique Can monitor memory usage data as well as time data Can easily be extended to allow remote profiling Cons: The instrumented VM is platform-specific
72
Instrumented VMs Java 2 (JDK 1.2 and higher) Microsoft JVM
information can be accessed through JVMPI the Java Virtual Machine Profiling Interface Microsoft JVM uses a COM-based interface to provide profiling information JProbe Profiler
73
Common Bottlenecks Although profiling can yield some surprises, often the bottlenecks are fairly obvious once the profiler points them out excessive heap expansion not using System.arraycopy() using the “+” operator with String objects using unbuffered I/O streams excessive memory allocations excessive calls to slow library methods
74
Memory Leaks Java doesn’t have “memory leaks” like a C or C++ program, but… Some Java programs exhibit classic “memory leak” behavior: their memory usage grows, unbounded, over time Memory leaks usually also lead to performance problems once the process starts getting swapped out
75
What is a Memory Leak? Allocated Reachable Live exists on the heap
a path exists from some root to it Live program may use it along some future execution path
76
What is a memory leak? Memory leak in C/C++ allocated reachable
Memory leak in Java live
77
Loiterers We like to call these objects “loiterers” because:
they’re not really leaks - you can probably still release the memory somehow we don’t want to confuse Java-heap problems with native-heap problems caused by native code, which could be real memory leaks
78
Lapsed Listener Object added to collection, not removed
e.g. event listener, observer collection size can grow without bound iteration over “dead” objects degrades performance Most frequent loitering pattern Swing and AWT have had many occurs easily in any large framework C++: small loiterer or dangling pointer
79
Lingerer Reference used transiently by long-term object
Reference always reset on next use e.g. associations with menu items e.g. global action or service Not a problem in C++ benign dangling reference
80
Laggard Object changes state, some references still refer to previous state also a hard-to-find bug Common culprits changing life-cycle of class (e.g. into a singleton) constructor sets up state caches expensive-to-determine object state changes, cache not maintained C++: dangling pointer
81
Limbo Reference pinned by long-running thread Common culprits
references on stack GC doesn’t do local liveness analysis Common culprits thread stall expensive setup calls long-running analysis C++: placement of destructors
82
Loiterers For more information on causes of loiterers and how to prevent them, see the article: ‘How Do You Plug Java Memory Leaks?’ in Dr.Dobb’s, Feb. 2000 also at:
83
Memory Leaks So, how can you identify & track down memory leaks?
This is almost impossible to do without a memory analysis tool Some tools: HAT (defunct) JProbe OptimizeIt
84
Questions?
85
Fin Check out JProbe at: http://www.klgroup.com/jprobe
Contact me at:
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.