1 / 85

Java Debugging & Profiling Techniques

Java Debugging & Profiling Techniques. Ethan Henry egh@klg.com KL Group http://www.klgroup.com. Overview. This session will touch on three major topics: Debugging and Profiling plus Memory Leaks in Java. Debugging. What’s debugging? If you don’t already know…

Télécharger la présentation

Java Debugging & Profiling Techniques

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. JavaDebugging & ProfilingTechniques Ethan Henry egh@klg.com KL Group http://www.klgroup.com

  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 • http://www.eiffel.com/doc/manuals/technology/contract/ariane/index.html

  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) { printing = 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) { if(printing) 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: • http://www.halcyon.com/nickx/JContracts/ • There’s a JSR on the subject as well: • http://java.sun.com/aboutJava/communityprocess/jsr/jsr_041_asrt.html

  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. 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 Errors

  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.lang.Object.wait(Native Method) at java.lang.Object.wait(Compiled Code) 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.Object.wait(Native Method) at java.lang.ref.ReferenceQueue.remove(Compiled Code) 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: sun.awt.PostEventQueue@1916E10/1957BC0: <unowned> Waiting to be notified: "SunToolkit.PostEventQueue-0" (0x8a5b70) java.awt.EventQueue@1916D90/19579B8: <unowned> Waiting to be notified: "AWT-EventQueue-0" (0x8a3680) java.lang.ref.ReferenceQueue$Lock@18F9338/192ED78: <unowned> Waiting to be notified: "Finalizer" (0x8209d0) java.lang.ref.Reference$Lock@18F93C0/192E8A8: <unowned> Waiting to be notified: "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: • http://developer.java.sun.com/developer/technicalArticles/Programming/Stacktrace • 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) • http://www.borland.com/jbuilder • NetBeans Developer/Forte for Java (IDE) • http://www.netbeans.com • Commercial: • Metamata Debug • http://www.metamata.com • Karmira BugSeeker • http://www.karmira.com

  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. JDK 1.0/1.1 Debugging API • The basic debugger architecture: h Java Interpreter JavaVM Agent Request Reply Instance ofRemoteDebugger Java DebuggingClient

More Related