Presentation is loading. Please wait.

Presentation is loading. Please wait.

Advanced Enterprise Debugging Techniques Neal Ford Application Architect ThoughtWorks memeagora.blogspot.com.

Similar presentations


Presentation on theme: "Advanced Enterprise Debugging Techniques Neal Ford Application Architect ThoughtWorks memeagora.blogspot.com."— Presentation transcript:

1 Advanced Enterprise Debugging Techniques Neal Ford Application Architect ThoughtWorks memeagora.blogspot.com

2 2 Questions, Slides, and Samples Please feel free to ask questions anytime The slides and samples will be available at (I’ll show this again at the end)

3 3 What This Session Covers: Remote debugging Remote debugging in IDE’s (Don’t scoff) jdb Forensic debugging Debugging web applications Debugging class loaders Groovy enterprise debugging Automating common tasks

4 4 Remote Debugging in Java Built into the platform Found in JavaDocs at jdk1.5.0/docs/guide/jpda/architecture.html

5 5 Enable Debugging on the VM Add some parameters to your JVM startup ParameterPurpose -XdebugEnables debugging support in the VM -Xrunjdwp: Loads the in-process debugging libraries and selects the transport mechanism for communciations

6 6 runjdwp Options NameDescription helpPrints a brief help message and exits the VM. transportContains the name of the transport you want to use when connecting to the debugger. serverIf y, listens for a debugger application to attach; otherwise, attaches to the debugger application at the specified address. If y and no address is specified, chooses a transport address at which to listen for a debugger application, and prints the address to the standard output stream.

7 7 runjdwp Options NameDescription addressContains the transport address for the connection. If server=n, attempts to attach to debugger application at this address. If server=y, listens for a connection at this address. launchAt completion of Java Debugging Wire Protocol (JDWP) initialization, launches the process given in this string. This option is used in combination with onthrow and/or onuncaught to provide just-in-time debugging, in which a debugger process is launched when a particular event occurs in this VM. onthrowDelays initialization of the JDWP library until an exception of the given class is thrown in this VM. The class name is package-qualified. Connection establishment is included in JDWP initialization, so it will not begin until the exception is thrown.

8 8 runjdwp Options NameDescription onuncaughtIf y, delays initialization of the JDWP library until an uncaught exception is thrown in this VM. Connection establishment is included in JDWP initialization, so it will not begin until the exception is thrown. stdallocBy default, the JDWP reference implementation uses an alternate allocator for its memory allocation. If y, the standard C runtime library allocator will be used. This option is mainly for testing; use it with care. Deadlocks can occur in this VM if the alternative allocator is disabled.

9 9 runjdwp Options NameDescription strictIf y, assumes strict Java Virtual Machine Debugging Interface (JVMDI) conformance. This will disable all workarounds to known bugs in JVMDI implementations. This option is mainly for testing and should be used with care. suspendIf y, VMStartEvent has a suspendPolicy of SUSPEND_ALL. If n" VMStartEvent has a suspendPolicy of SUSPEND_NONE.

10 10 The Ones You Care About Transport dt_shmem- Uses Windows shared memory primitives to communicate information between debugger applications and the target VM. Shortcomings Only works on Windows Only works when both VMs are running on the same machine dt_socket- Allows the debugger and debuggee to communicate over a socket Advantages Works across platform Works across machines

11 11 The Ones You Care About Address dt-shmem – The “address” of the shared memory An arbitrary string that the debugger and debuggee agree upon dt_socket – The socket used for communication Server Set to “Y” Suspend Set to “N” unless you are debugging startup behavior

12 12 Remote Debugging in Eclipse

13 13 Remote Debugging in IntelliJ

14 14 Remote Debugging in JBuilder

15 15 When It's All You've Got: jdb What’s the only debugger that you absolutely know will be available everywhere? On you development machine On the production server At a remote client’s site jdb – the command-line debugger that comes with the SDK It is surprisingly capable once you learn how to use it To see a list of commands, start it and type ?

16 16 The jdb Designer Surface

17 17 Some choice jdb commands CommandDescription runStarts execution of the application’s main class ThreadsLists the threads in the application, both running and suspended threadSet the default thread where Dumps a thread’s stack print Prints the value of an expression stop at : Sets a breakpoint at a line stop at. Creates a method breakpoint

18 18 The jdb Recipe 1.Start the application server in debug mode. 2.Attach to the source path for your code. 3.Set one or more breakpoints, either on line numbers or contingent on method invocations. 4.Run the application. 5.Find the thread ID for your application. 6.Set it as the default thread. 7.Invoke your application in a browser and interact with it until you hit a breakpoint. 8.Use step and/or next to walk through your code. 9.Use dump, locals, and eval to analyze your variables. 10. If you need to make a small change to a file and test it, use redefine to load the new class file. 11. Use cont to resume execution of the application until the next breakpoint. 12. Iterate until done.

19 19 Effective Debugging To often, developers only set line breakpoints Every debugger (including jdb) allows you to set a variety of breakpoint types (all conditional) Line Method Class Exception Use the debugger wisely If you know that a certain method causes a problem when a condition becomes true, set that up as a breakpoint

20 20 Effective Debugging One of the keys to effective debugging is to not use brute force System.out.println() Line breakpoints There is always a sense of urgency when debugging – stop and think! I know that you are behind schedule, but you’re just making it worse! Step away from the keyboard Don’t ever say: “But that’s impossible!” Or, “But it works on my machine!”

21 21 Forensic debugging using loggers Loggers are the best way to do forensic debugging Logging setup is well documented just about everywhere Use the levels wisely If you do need to get down to the “debug” level, use tools grep will help you find just what you are looking for Don’t go scroll blind Use ChainSaw

22 22 Using Aspects to Instrument Loggers One of the best use of Aspects is to inject logging code Even though great effort has been made to make the logging tests cheap, there is still overhead There’s no overhead if the code isn’t there! Aspects allow you to specifically target code only when you need to

23 23 Debugging Web Applications Firefox developer’s toolbar Bookmarklets Bookmarks (generally JavaScript) that expose information about the page It is sometimes amazing how much you can find out Search for Bookmarklets

24 24 Tapestry Debugging JSP’s is tough Mixed HTML, JavaScript, JSP custom tags, and JSP Tapestry has the best debugging aid of any web framework Inspector

25 25 Tapestry’s Inspector

26 26 Debugging Hibernate With some JDBC drivers (i.e., PostgreSQL) and batched updates with Hibernate: An exception is thrown (e.g. when a foreign key constraint is violated or not null column is left out, etc.) This SQLException is wrapped in a PBatchUpdateException This PBatchUpdateException is wrapped in a HibernateException The HibernateException is written to the log Hibernate uses standard stacktrace routines from JDK 1.4 The call to getNextException() from SQLException is never made

27 27 Debugging Hibernate: 2 Solutions Disable batch updating in the hibernate.properties file: hibernate.jdbc.batch_size = 0 “Walk” the exception hierarchy yourself, using a combination of getNextException() and getCause() Note that Hibernate isn’t walking the exception chain in every case May be losing information even without batch updates Exceptions aren’t linked via the 1.4 mechanism This is deliberate – each exception in the chain may have an independent cause) Hibernate needs fixing!

28 28 Debugging Class Loaders One of the bane’s of application servers are class loader issues Class loaders are responsible for loading classes within the VM When you execute a Java application, the native Java class loader loads (the bootstrap class loader) The JVM loads 2 other class loaders by default Extension class loader Application class loader

29 29 Class loaders Core Java Classes Extensions (javax.* and classes from the ext directory) Your application

30 30 Class loaders Class loaders use the delegation model to load classes Each class loader defers to its parent In application servers, each deployed application generally gets its own class loader EAR files get a single class loader for both web and EJB These class loaders are responsible for loading and unloading classes

31 31 Application Server Class Loaders

32 32 Why Should You Care? Shared libraries Logger packages (like Log4J) XML parsers You have several options: Deploy the shared library on the application server’s class loader Move it to the app server’s lib directory Can cause problems

33 33 Class Loader Recipe If the utility class is required only by your web application, move it to WEB-INF/lib If you have a web application and EJB’s that don’t share a class loader Make an entry in your manifest file for the EJB Specify all the utility classes using the Classpath entry Keep this utility JAR file either in a shared location where both web and EJB’s can see it (but off the app server’s boot classpath)

34 34 Debugging Class Loader Problems You usually don’t see a problem when the class loads (or fails to load) The toString() methods of the JDK class loaders don’t provide much information What to do when you get the dreaded ClassNotFound exception 1.Look for the line where your class loader's loadClass() call is involved 2.Figure out what class loader is used there. 3.Figure out the parent class loaders recursively until you find the bootstrap class loader. 4.Figure out why the class cannot be found by any of these class loaders.

35 35 Debugging Class Loader Problems Some causes: An archive, directory, or other source for the classes was not added to the class loader asked to load the class, or to its parent. A class loader's parent is not set correctly. The wrong class loader is used to load the class in question.

36 36 Debugging Class Loader Problems The 3 rd option happens very easily In J2EE, an EJB is required to use the thread context class loader ( Thread.currentThread.getContextClassLoader() ) to load classes Some developers use Class.forName() to load a class without specifying the thread context class loader as the current class loader

37 37 Symbolic-link Class Not Found If a symbolic link cannot be found, a NoClassDefFoundError occurs This means that the code has been successfully compiled but can’t find the referenced class at runtime How to investigate this problem: 1.Find the NoClassDefFoundError and print out its stack trace. 2.Find the topmost line in the stack trace that is not class-loader- related. This most likely indicates the class of the symbolic link that was not found.

38 38 Symbolic-link Class Not Found How to investigate this problem: 3.Figure out the class loader of the class containing the offending symbolic link. 4.List the parent class loaders recursively. 5.Figure out why the class is not available to any of these class loaders. Potential causes: An archive, directory, or other source for the classes was not added to the class loader asked to load the class, or to its parent. A class loader's parent is not set correctly. Symbolic links in a class are unaccessible by the containing class's class loader

39 39 Last Resort to Solve CL Issues Patch the JDK’s Class Loader with an improved toString() method 1.Take the source of java.lang.ClassLoader, java.security.SecureClassLoader and java.net.URLClassLoader and copy them. 2.Add the desired toString() method and make sure that every class loader prints out its own address by using super.toString() so that you can test if class loaders from the same class are identical or not. 3.Jar them up 4.Add -Xbootclasspath/p: to your script that starts Java.

40 40 Last Resort We need 3 pieces of information from the class loader An indicator of the instance What archives are available to this class loader Information about the parent class loader

41 41 Sample toString() from the Updated System CL public String toString() { if( getParent() != null ) { return "java.net.URLClassLoader:\n" + "hashcode: " + hashCode() + "\n" + "URLs: " + java.util.Arrays.asList( getURLs() ) + "\n" + "parent { " + getParent() + " }\n"; } else { return "java.net.URLClassLoader:\n" + "hashcode: " + hashCode() + "\n" + "URLs: " + java.util.Arrays.asList( getURLs() ) + "\n"; }

42 42 Dynamic Server-side Debugging Sometimes you need a little snippet of information from the application server that is very difficult to get from a debugger without Herculean effort Chris Judd’s Script Debugger A servlet that includes Groovy and a way to dynamically execute Groovy scripts Groovy allows you to ferret out all sorts of server side information

43 43 Judd Script Debugger Need to know which XML parser is being loaded? Interested in a particular JNDI resource? import javax.xml.parsers.DocumentBuilderFactory as dbf clazz = dbf.newInstance().newDocumentBuilder().class clazz.protectionDomain.codeSource.location import javax.naming.* ctx = new InitialContext() ctx.lookup("java:/DefaultDS")

44 44 Judd Script Debugger Want to see all session variables? output = "" sessionVars = [:] for (n in session.attributeNames) { sessionVars[n] = session.getAttribute(n) } sessionVars.each { s | output = output + "${s.key} = ${s.value} " } output

45 45 Automating Debugging Tasks How many times have you walked the same path through a web application to get to the point that you want to debug? Stop working so hard for your computer! Set up jWebUnit to “walk through” the application for you to a certain point jWebUnit is designed for unit testing but it has great automation for driving web applications While you are there, go ahead and write a unit test!

46 46 Automating Debugging Tasks What if you need to interact with the application once you’ve gotten to the critical point? Selenium A testing tool for web applications Selenium uses JavaScript and IFrames to embed a test automation engine in your browser This technique works with any JavaScript-enabled browser Developed by ThoughtWorks for internal use It was so useful that we’ve open-sourced it Still in early stages (0.4 is latest version)

47 47 How Does Selenium Work?

48 48 Using Selenium as a Debugging Aid Test cases are trivial to write Use Selenium to “walk” your web application to the point where you want to debug it Either Take over by hand Use Selenium’s step behavior to check individual behavior

49 49 Words of Debugging Wisdom From The Pragmatic Programmer: “Embrace the fact that debugging is just problem solving, and attack it as such.” Tip #24: Fix the problem, not the blame. Tip #25: Don’t Panic The Pragmatic Programmer has lots of information about the debugging mindset Don’t use brute force! Work the problem Apply as much ingenuity to debugging as to the design that got you here

50 Neal Ford memeagora.blogspot.com Questions? Samples & slides at This work is licensed under a Creative Commons Attribution- NonCommercial-ShareAlike 2.5 license.


Download ppt "Advanced Enterprise Debugging Techniques Neal Ford Application Architect ThoughtWorks memeagora.blogspot.com."

Similar presentations


Ads by Google