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


Print Groups of ObjectWrapper Fields

The startSection() mechanism described in the previous topic provides one way to group multiple related fields in the report. But in the case of multiple fields that are all associated with one particular ObjectWrapper analyzer object, there is an even more powerful facility:

public class WASThreadPoolsSample2 extends WASAnalyzerBase implements IReport {

public IAnalysisReport produceReport() { IAnalysisReport out = allocateReport(null); ObjectWrapperCollection pools = ObjectWrapperCollection.getObjectInstances(getContext(), "com/ibm/ws/util/ThreadPool");

out.printField("Number of thread pools", pools.size());

for (int index = 0; index < pools.size(); index++) { ObjectWrapper pool = (ObjectWrapper) pools.get(index);

/*NEW*/ IAnalysisReport out2 = pool.startPrintGroup(out, "Thread Pool", pool.getParent(), ObjectWrapper.MODE_NONE, IAnalysisReport.TAG_STANDOUT); {

pool.printValueAtPath(out2, "Pool name", "name");

out2.startFormatSection(IAnalysisReport.FORMAT_COLUMNS, "1 1"); { pool.printValueAtPath(out2, "Min size", "minimumPoolSize_"); pool.printValueAtPath(out2, "Max size", "maximumPoolSize_"); } out2.endSection();

pool.printValueAtPath(out2, "Current size", "poolSize_"); pool.printValueAtPath(out2, "List of Threads", "threads_");

/*NEW*/ } pool.endPrintGroup();

} return out; } }

Basically, we have replaced the startSection()/endSection() calls on the report object, with calls to startPrintGroup()/endPrintGroup() on the ObjectWrapper analyzer object from which we intend to use to generate most of the body of the section.

The output looks as follows:

Number of thread pools: 14

Thread Pool: com/ibm/ws/util/ThreadPool@0x00AA7B30 Pool name: "ORB.thread.pool" Min size: 10 Max size: 50 Current size: 0 List of Threads: java/util/HashMap@0x00AA7B98

Thread Pool: com/ibm/ws/util/ThreadPool@0x0102D4B8 Pool name: "HAManager.thread.pool" Min size: 2 Max size: 2 Current size: 1 List of Threads: java/util/HashMap@0x0102D520

...

The output in this example may not look very different from the output obtained with startSection()/endSection(), but there are actually several very important differences:


Section title includes object reference

When using IAnalysisReport.startSection(), the title of the section that groups all the field related to one particular thread pool object from the dump (represented by an ObjectWrapper), can only be a static, literal string; "Thread Pool:".

When using ObjectWrapper.startPrintGroup(), the title of the section automatically contains a static label followed by a reference to the object represented by this ObjectWrapper: "Thread Pool: com/ibm/ws/util/ThreadPool@0x00AA7B30"


Hyperlinks to this report section

The group of fields defined by startPrintGroup() is tightly associated with an object reference to the object represented by this ObjectWrapper, as specified by the pool.getParent() argument in third position in this call. If anywhere else in the report, there is some item that uses printFieldValue() (or other similar function) to print the value of a field in some other object, that happens to be a reference to this object, that value will be represented in the report as HTML hyperlink that links back to this group of fields.

In other words, if object X printed somewhere in the report contains a field that references object Y, and you click on the value "Y", you will jump directly to the section of the report that show the details (fields) of object Y. This can be very useful for navigation in long complex reports where there are many cross-references between many objects printed throughout the long report.

For more details about this mechanism, see the main API reference in the Dump Analyzer tool documentation.

Of course, this hyperlink facility only works when the report is formatted into HTML... but that is the default format when displaying reports in the Dump Analyzer tool in ISA.


Print the "missing" fields

In the example above, we used ObjectWrapper.MODE_NONE as the fourth parameter to startPrintGroup and this generated the simple output above.

But there are other options that cause the ObjectWrapper to automatically add other fields in the report, without having to list these fields explicitly in the analyzer. For example, if we use

IAnalysisReport out2 = pool.startPrintGroup(out, "Thread Pool", pool.getParent(), ObjectWrapper.MODE_DEFAULT | ObjectWrapper.MODE_INCLUDE_HEADER | ObjectWrapper.MODE_INCLUDE_SIGNATURE, IAnalysisReport.TAG_STANDOUT); {

The report segment generated for this startPrintGroup()/endPrintGroup() block will show the fields that are explicitly printed by calls to printValueAtPath() as before, followed by a new subsection that automatically prints all the other non-final fields from the target object, that have not been printed explicitly above. Other options provide control over whether to print static or non-static fields, whether to include signatures, headers, etc.

Here is an example of output with these options:

Thread Pool: com/ibm/ws/util/ThreadPool@0x00AA7B30
      Pool name: "ORB.thread.pool"
      Min size: 10                       Max size: 50                 
      Current size: 0
      List of Threads: java/util/HashMap@0x00AA7B98
      --- Other fields not printed above ( instance-nonfinal static-nonfinal ):
         ZERO_OBJECTS: [java/lang/Object@0x022C36E0    (static : [Ljava/lang/Object;)
         ZERO_TP_LISTENERS: [com/ibm/ws/util/ThreadPoolListener@0x022C2578  (private static : [Lcom/ibm/ws/util/ThreadPoolListener;)

_isDecoratedZOS: false

      (protected : Z)
         activeThreads: 0                              (protected : I)
         class$com$ibm$ws$util$ThreadPool: java/lang/Class@0x15596B40  (static : Ljava/lang/Class;)

class$java$lang$Object: null

(static : Ljava/lang/Class;)
         class$java$lang$Thread: java/lang/Class@0x11554B88  (static : Ljava/lang/Class;)

clearJavaLangThreadLocals: false
     (private : Z)  
         daemonId: -1                                  (private : I)  

growasneeded: false


(protected : Z)

isZOS: false


       (private : Z)  
         keepAliveTime_: 3500                          (protected : J)

lastThreadCheckDidntComplete: false
  (private : Z)  
         monitorPlugin: com/ibm/ws/runtime/component/ThreadPoolMgrImpl$ThreadPoolMonitorAdapter@0x00AF11B0  (private : Lcom/ibm/ws/util/ThreadPool$MonitorPlugin;)
         requestBuffer: com/ibm/ws/util/BoundedBuffer@0x00AA7F98  (protected : Lcom/ibm/ws/util/BoundedBuffer;)
         requestBufferExpansionLimit_: 500             (private : I)  
         requestBufferInitialCapacity_: 50             (private : I)  

shutdown_: false


   (protected : Z)
         tc: com/ibm/ejs/ras/TraceComponent@0x022C2300  (private static : Lcom/ibm/ejs/ras/TraceComponent;)
         threadLocalsField: java/lang/reflect/Field@0x022C2848  (private static : Ljava/lang/reflect/Field;)
         threadPoolListeners: [com/ibm/ws/util/ThreadPoolListener@0x0303FE00  (protected : [Lcom/ibm/ws/util/ThreadPoolListener;)
         threadid: 0                                   (protected : I)
         threadpriority: 5                             (protected : I)

xMemSetupThread: null

       (protected static : Ljava/lang/reflect/Method;)

This mechanism is extremely useful when creating very detailed reports where it might be extremely tedious to explicitly list every field of every data structure to be included in the report, or during the development phase of a new report, when we might not yet have clearly decided which fields are important to include or not.


Secondary report used within the group

Finally, one should note one peculiarity of the use of the startPrintGroup()/endPrintGroup() mechanism. startPrintGroup() actually returns a new report object, and that second report object, not the original one, should be used in all calls to printValueAtPath(), etc. within the group (a runtime occurs during analysis if this requirement is violated).

This is because the implementation of startPrintGroup() actually relies on putting the information from the group in a secondary report, which is subsequently embedded in the main report. This is a relatively common pattern, that we will encounter in other situations as we work through complex analyzer implementations.


Next Topic


Work with J2SE Collections