The JProbe ServerSide Suite, version 2.5, consists of three related tools: a Profiler/Memory Debugger, a Threadalyzer and a Coverage product. All can use the LaunchPad to start profiling sessions against applications, applets and servlets, or use their built-in launch facilities
Each product takes a different approach to making your Java code more solid. The Coverage tool helps test all source code paths, the Profiler/Memory Debugger is used during development and later during production to tune the code, and the Threadalyzer helps to identify (potential) locking/synchronization issues.
With the direct support of Java 2 (using the JVM debugger and profiler interfaces), KL Group removed one of the main differentiators of the product. Earlier versions relied solely on instrumented JVMs to provide accurate measurements, but only approximated the real production environment (instrumented versions of JDK 1.1.7 and 1.1.8 are still supplied with the product). The Java 2 support is excellent, providing line-by-line detail not directly available using the JVMDI/JVMPI APIs. Note that the Solaris production version of Java 2 doesn't support the JVMDI or JVMPI required by JProbe, so you're still only approximating the real environment on Solaris. KL Group is working toward providing support for the Solaris Java 2 production version.
All three products use a similar metaphor of "snapshots" that can be loaded from and saved to a disk, given names and unloaded. These show up on the left-hand panels of the products. Snapshots can be redisplayed, analyzed and merged if appropriate. The right-hand panels display information specific to the snapshot, allowing drill-down actions where appropriate. Pattern-based filtering can be used to (de)select which packages/classes are of importance. Triggers are also provided that permit specific actions (e.g., starting/pausing/stopping/clearing event recording) when a class (or one of its specified methods) is entered or exited.
Filtering and triggers allow you to set up sophisticated testing schemes, but you pay a maintenance price, especially on "moving target" complex products with frequent API changes. The tools let you control a JVM that's executing remotely, but the detailed debug information generated needs to be delivered in a separate way (perhaps mounted drives or something similar). Although there's no way to run all three tools in parallel against the same JVM, the same start-up files can be used for the different tools from the command line. For many tables in the product there are popup menus that allow you to show more columns in the tables. (In most tables package names weren't displayed by default.) I noticed GUI refresh problems and misreported line numbers; also, the keyboard scrolling doesn't seem to work in the built-in source browser. Command-line options are available for all three tools and their API is also documented in the help files.
Let's look at the tools one by one. When using the LaunchPad, you need to select one of the three modes of operation; the selected viewing tool can then be attached to the JVM that's running (see Figure 1). LaunchPad functionality can be invoked from the command line, allowing extensive configuration file and parameter-based scripting. In addition to controlling the data collection of LaunchPad by the other tools, this allows standalone data collection operation, with the resulting files later analyzed by the other tools. I found some inconsistent behavior when using the LaunchPad. It didn't restore the JVM version selected or the triggers for other modes of operation when switched between them. Sometimes the interaction between the LaunchPad and the other tools wasn't well synchronized. For example, in some cases the Profiler and the LaunchPad weren't pointing to the same snapshot directory or were running different JVMs, causing strange errors.
These different settings may be desirable when running several instances of LaunchPad on different TCP/IP ports, but one would think that the two applications would be synchronized during connection time. Programs can be run from the tools without using the LaunchPad, but in this case there seems to be no way to load/save the arguments set.
The Profiler/Memory Debugger has the busiest interface of the three products, because of its extensive visualization and drill-down capabilities (see Figure 2). The tool presents a twofold approach in which the Profiler generates both the timing and the number of object allocation snapshots, and the Memory Debugger generates object reference graphs in memory. While the timing approach is the more usual one, the number of objects generating information is of great importance because of the cost of creating/destroying objects. Also, analyzing object reference graphs helps identify potential memory leaks, when objects are kept from garbage collection, by referencing them unintentionally. Instead of generating differences between snapshots taken at the different times, the tool allows you to do counts relative to a cleared baseline. Even when helped with the well-done UI of the tool, the information presented doesn't always map easily into a good understanding of where the bottlenecks are in complex situations. Finding real problem areas requires iterations, and the ability to set up/save filtering and triggers definitely helps.
Threadalyzer (see Figure 3) has the fattest documentation of the three tools, indicating that it's conceptually different from the usual profiling tools. As described below, different levels of analysis are available, and running some of them slows the application to a crawl as it cross-inspects variables and where they're accessed.
According to the documentation, thread is expected to behave differently under different JVMs, so it's wise to run your production JVM with the Threadalyzer tool, which is a concern with Solaris. The tool looks for the following thread-related problems:
As analyzing requires no instrumentation of the code, it can also be used to discover problems with system or third-party libraries, and it may prove very useful in testing for multithreading issues in Swing code. A visualizer option is also included, allowing a quick overview of all threads and their state. The user will likely see many false alarms when using the tool, as mentioned in the documentation supplied, but the nice tool layout will help you narrow in on the important ones. The tool is useful to stress-test code with complex threading, but because thread-related states are difficult to (re)create, you may still want to continue reviewing any code with complex threading.
- Deadlocks: When resources are locked in a different order on more than one thread
- Potential deadlocks: Holding a resource while in a wait state and locking order differences between threads
- Thread stalls: When a thread is in a wait state longer than the threshold set
- Data races: When different threads try to read/write the same variable at the same time; detected using "happens before" and "lock covers" algorithms
The easy-to-use Coverage tool fits nicely with the other debug tools, as it uses the line number in file information to create a line-level detail coverage map (see Figure 4). It lets you merge generated coverage maps and view the results of several runs, perhaps with different start-up parameters as one map. It also generates detailed summary reports in HTML format.
The merging and reporting functionality are also available as standalone programs, and the Java API of the Coverage tool allows extensive automation.
JProbe hooks into Symantec's VisualCafé and IBM's VisualAge, allowing you to launch the tools from the menu and editing source files inside their environment. It also allows easy export of files from VisualAge's built-in source-control repository. The ServerSide Suite also provides templates to connect to several servlet engines (including JRun, WebLogic, WebSphere, Servlet Runner), enabling easy profiling of servlets in these different environments.
I noticed several problems with the tools. I had crashes in both the JProbe tools and the JVM itself - maybe the JVMDI/JVMPI interfaces were overexercised. Another problem was nonintuitive handling of the "current directory" in complex projects - in many cases you need to repoint the tool to a source file you used a second ago even though it's relative to the current directory specified in your project and/or could be located using your CLASSPATH.
Even with these annoyances, JProbe is a recommended tool for both client and server-side code development.
Gabor Liptak is an independent consultant with more
than 10 years of industry experience. He is currently
an architect of a Java e-commerce project.
For more information on SonicMQ, visit www.sonicmq.com