Express (Distributed operating systems), v8.0 > Troubleshoot and support > Analyzing application server Java system dumps with the IBM Monitoring and Diagnostic Tools for Java - Dump Analyzer > Write Dump Analyzer modules for WAS diagnostics - Tutorial


Tutorial: Writing Dump Analyzer modules for WAS diagnostics


Invoke DTFJ Functions

Most of the work done by the analyzer in this example relates to examining the contents of various WAS data structures, for which we use special pre-defined analyzer from the library, such as ObjectWrapper. In order to do their work, these analyzers call lower-level functions from the DTFJ interface provided by the JDK as a standardized interface to access the contents of a dump. In effect, this library of analyzers essentially provides a level of abstraction on top of the DTFJ interface, with higher-level specialized functions.

But sometimes, we may want to access low-level functions from the DTFJ interface directly, to access some combination of information that is not pre-defined in some analyzer from the library, or simply to access some information that is so basic and straightforward that there would be no point writing a specialized analyzer to encapsulate it. For this example, let us extend our WASThreadPoolsSample analyzer to count the total number of Java threads in the JVM being analyzed, and figure out how many of these Java threads are not part of a WAS thread pool:

private int countJVMThreads() {
   JavaRuntime runtime = getContext().getCurrentJavaRuntime();
   Iterator it = runtime.getThreads();
   int count = 0;
   while (it.hasNext()) {
       it.next();
       count++;

   return count;
}

We add the method countJVMThreads() in the class implementing the WASThreadPoolsSample analyzer. And in the body of the produceReport() method, we add the line

out.printField("Number of JVM threads not in a pool", countJVMThreads() - numberOfAllocatedThreads);

The key elements in this code are as follows:


Gaining access to a DTFJ runtime reference

The context associated with each analyzer, obtained through a call to getContext(), provides us with the necessary starting point to access the DTFJ-level information. The getCurrentJavaRuntime() method of the context returns a reference to the DTFJ JavaRuntime object that represents the runtime of the JVM being analyzed. From this JavaRuntime, we can call other DTFJ methods, in this case getThreads() which returns the list of all Java threads.

The context contains a few other methods to gain access to other key entities in the DTFJ object hierarchy:

In general, once you get a hold of one of these DTFJ starting points in your analyzer, you can invoke any applicable DTFJ methods on it, use them to obtain DTFJ references to other types of items in the JVM, call further DTFJ methods on them, etc. as necessary to extract any desired information.


Dealing with multiple DTFJ runtimes within one dump

The description of calls like getCurrentJavaRuntime(), getCurrentProcess(), etc. raises the question of what does "current" mean in this context. This concept is introduced because, in some cases and on some platforms (esp. z/OS), a single dump (known in DTFJ as an Image) may contain multiple address spaces (DTFJ ImageAddressSpace), which in turn may contain multiple processes (DTFJ ImageProcess), which in turn may contain multiple runtimes (DTFJ ManagedRuntime or JavaRuntime). When this is the case, the analyzer actually operates in the context of one particular tuple of address space / process / runtime, represented by the context object associated with that analyzer. If necessary, the same analyzer may be executed multiple times, each time with a different context corresponding to a different tuple. See the API documentation for the IAnalyzerContext interface for further details about this mechanism.


Next Topic


Generate Reports with a Summary and a Details Section