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 a new analysis module or script > Write and running a new analysis module


The structure of a DTFJ Image object

In this section we will outline some of the primary classes which are found within the DTFJ Image which is the result of reading a jextracted dump with an appropriate ImageFactory. The primary class is of course the Image itself which is a representation of the entire dump. This has a number of attributes that describe the dump such as the host name and contains a set of ImageAddressSpace objects. Typically there will be a single address space in a dump but some environments allow the inclusion of more than one. Within an address space we may find one or more ImageProcess objects, one of which may be current. In general the classes called Image* represent items which are not specific to Java and thus from an ImageProcess we can iterate over the set of ImageModules that represent the libraries loaded in the process and the set of ImageThreads that represent the native threads active in the process. An ImageThread will return an iterator over the set of ImageRegisters which in turn give access to the current values in those registers. Finally an ImagePointer represents a specific memory location in an address space and is often used to give a unique identity to some object. Returning to an ImageProcess we can iterate over potentially many separate ManagedRuntime objects which define the most generic form of runtime. In most of the dumps that we are analyzing we would expect to find a single runtime which will be a specialized form of the ManagedRuntime; a JavaRuntime.

Once we are looking at a JavaRuntime object we are able to examine the key state of the Java VM at the time of the dump. Hence we can iterate over the JavaClassLoaders, JavaThreads, JavaMonitors and JavaHeaps (there may be more than one). We can also iterate over the methods which the JIT has compiled. From the JavaClassLoader we can iterate over the list of defined and cached classes which in turn allow us to iterate over the methods and fields. From a JavaHeap we can iterate over all the objects in that heap and then reflect on the values in the fields of those objects. The result is that we can write analysis code which will examine the finest details of the state represented in the dump and then reach conclusions on the validity of that state.

Within DTFJ there are various errors that may be encountered and these are indicated in various ways. When reading data from a dump we may discover that some data is either missing or in some way corrupt. It may be missing either because the particular dump format does not provide the data or it may be that at the time of the failure the data was not available. Data corruption is generally the result of some memory overwrite that has occurred and this may have been the cause of the dump. Within the DTFJ interface missing data is signalled by throwing DataUnavailable and corrupt data is signalled by throwing CorruptDataException. There is a subtlety within DTFJ concerning the handling of these error conditions when an Iterator is being used to iterate over the elements of a collection such as all the Java threads. If during the iteration we discover some corrupt data this is signalled to the user by returning a special sort of Object from Iterator.next(). Instead of the expected object class (in this example JavaThread) we return an Object which implements CorruptData. The precise class of that Object is left to the implementor of the image factory which created the Image being read but in the simplest case it will be a class which extends Object and implements CorruptData. This effectively just informs the reader that some corrupt data has been encountered. There may alternatively be implementations which choose to return an Object which extends JavaThread and implements CorruptData but which throws CorruptDataException in response to some or all of the methods which get information from the thread object. This implementation would be useful in cases where the corruption was detectable but not total; some useful information could still be read.

The handling of these error conditions is of course a large part of the design of any analysis module and it is not possible to be prescriptive. Within DumpAnalyzer you can adopt a number of policies for dealing with the errors. The simplest is to wrap any code which invokes methods on the DTFJ objects with a try .. catch block and catch DTFJException DTFJException (the superclass of both DataUnavailable and CorruptDataException). In the catch clause simply invoke the handleError(message,exception) inherited from AnalyzerBase. This method will test the exception and maintain counts of both DataUnavailable and CorruptDataException. Any other exceptions will result in the message being added to the error log. At the end of the analysis the inherited methods getTotalCorruptDataErrors() and getTotalDataUnavailable() can be used to summarise the errors detected. Alternatively of course you might choose to implement catch clauses for the specific exceptions and either handle them in the analyzer or do some handling and then call the inherited handleError method.

In order to simplify the handling of CorruptData from iterators we provide the DTFJIterator which can either be instantiated directly (the constructor takes an Iterator and the current analyzer) or can be instantiated by the inherited buildSafeIterator() method. This iterator handles all occurrences of CorruptData and simply counts them. The caller is thus able to ignore possible corruption during the iteration and handle it when the iteration is complete (see An example of a more complex analyzer).


Javadoc for the DTFJ Classes

For the javadoc describing the classes outlined above please refer to the javadoc.

+

Search Tips   |   Advanced Search