Ibm Java 1.4.2 For Sap
Ibm Java 1.4.2 For Sap
iv Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
contents
Setting up and checking your Linux environment 127 Chapter 17. z/OS problem
Working directory . . . . . . . . . . . 127 determination . . . . . . . . . . . 151
Linux core files . . . . . . . . . . . . 127 Setting up and checking your z/OS environment 151
Threading libraries . . . . . . . . . . 128 Maintenance . . . . . . . . . . . . . 151
General debugging techniques . . . . . . . . 128 LE settings . . . . . . . . . . . . . 151
Starting Javadumps in Linux . . . . . . . 128 Environment variables . . . . . . . . . 151
Starting heapdumps in Linux . . . . . . . 128 Private storage usage . . . . . . . . . . 151
Using the dump extractor on Linux . . . . . 128 Setting up dumps . . . . . . . . . . . 152
Using core dumps . . . . . . . . . . . 129 General debugging techniques . . . . . . . . 152
Using system logs . . . . . . . . . . . 129 Starting Javadumps in z/OS . . . . . . . 152
Linux debugging commands . . . . . . . 130 Starting Heapdumps in z/OS . . . . . . . 152
Diagnosing crashes . . . . . . . . . . . 134 Using IPCS commands . . . . . . . . . 152
Checking the system environment . . . . . 134 Using dbx . . . . . . . . . . . . . 153
Gathering process information . . . . . . . 134 Interpreting error message IDs . . . . . . 153
Finding out about the Java environment . . . 134 Diagnosing crashes . . . . . . . . . . . 153
Debugging hangs . . . . . . . . . . . . 135 Documents to gather . . . . . . . . . . 153
Debugging memory leaks . . . . . . . . . 135 Determining the failing function . . . . . . 154
Debugging performance problems . . . . . . 135 Working with TDUMPs using IPCS . . . . . 155
System performance . . . . . . . . . . 135 Debugging hangs . . . . . . . . . . . . 160
JVM performance . . . . . . . . . . . 137 The process is deadlocked . . . . . . . . 160
JIT . . . . . . . . . . . . . . . . 138 The process is looping . . . . . . . . . 160
Collecting data from a fault condition in Linux . . 138 The process is performing badly . . . . . . 161
Collecting core files . . . . . . . . . . 138 Debugging memory leaks . . . . . . . . . 161
Producing Javadumps . . . . . . . . . 138 Allocations to LE HEAP . . . . . . . . . 161
Using system logs . . . . . . . . . . . 139 z/OS virtual storage . . . . . . . . . . 161
Determining the operating environment . . . 139 OutOfMemoryErrors . . . . . . . . . . 162
Sending information to Java Support . . . . 139 Debugging performance problems . . . . . . 163
Collecting additional diagnostic data . . . . 139 Collecting data from a fault condition in z/OS . . 164
Known limitations on Linux . . . . . . . . 140
Threads as processes . . . . . . . . . . 140
Floating stacks limitations . . . . . . . . 140
Chapter 18. Debugging the ORB . . . 165
glibc limitations . . . . . . . . . . . 140 Identifying an ORB problem . . . . . . . . 165
Font limitations . . . . . . . . . . . 141 What the ORB component contains . . . . . 165
CORBA limitations . . . . . . . . . . 141 What the ORB component does not contain . . 166
Platform-dependent problem . . . . . . . 166
JIT problem . . . . . . . . . . . . . 166
Chapter 16. Windows problem Fragmentation . . . . . . . . . . . . 166
determination . . . . . . . . . . . 143 Packaging . . . . . . . . . . . . . 166
Setting up and checking your Windows ORB versions . . . . . . . . . . . . 166
environment . . . . . . . . . . . . . . 143 Debug properties . . . . . . . . . . . . 167
Setting up your Windows environment for data ORB exceptions . . . . . . . . . . . . 168
collection . . . . . . . . . . . . . . 144 User exceptions . . . . . . . . . . . 168
General debugging techniques . . . . . . . . 145 System exceptions . . . . . . . . . . . 168
Starting Javadumps in Windows . . . . . . 145 Completion status and minor codes . . . . . 169
Starting Heapdumps in Windows . . . . . 145 Java2 security permissions for the ORB . . . . 169
Using the Cross-Platform Dump Formatter . . 145 Interpreting the stack trace . . . . . . . . . 170
System dump . . . . . . . . . . . . 145 Description string . . . . . . . . . . . 170
Diagnosing crashes in Windows . . . . . . . 146 Nested exceptions . . . . . . . . . . . 171
Data to send to IBM . . . . . . . . . . 147 Interpreting ORB traces . . . . . . . . . . 171
Debugging hangs . . . . . . . . . . . . 147 Message trace . . . . . . . . . . . . 171
Analyzing deadlocks . . . . . . . . . . 147 Comm traces . . . . . . . . . . . . 172
Getting a dump from a hung JVM . . . . . 147 Client or server . . . . . . . . . . . . 173
Debugging memory leaks . . . . . . . . . 147 Service contexts . . . . . . . . . . . 173
The Windows memory model . . . . . . . 148 Common problems . . . . . . . . . . . 174
Classifying leaks . . . . . . . . . . . 148 ORB application hangs . . . . . . . . . 174
Tracing leaks . . . . . . . . . . . . 148 Running the client without the server running
Using HeapDump to debug memory leaks . . 149 before the client is invoked . . . . . . . . 175
Debugging performance problems . . . . . . 149 Client and server are running, but not naming
Data required for submitting a bug report . . . 149 service. . . . . . . . . . . . . . . 175
Frequently reported problems . . . . . . . 150 Running the client with MACHINE2 (client)
Collecting data from a fault condition in Windows 150 unplugged from the network . . . . . . . 176
Contents v
contents
IBM ORB service: collecting data . . . . . . . 176 Using VerboseGC to obtain heap information . . . 208
Preliminary tests . . . . . . . . . . . 176
Data to be collected . . . . . . . . . . 177 Chapter 23. JVM dump initiation . . . 209
Overview. . . . . . . . . . . . . . . 209
Chapter 19. NLS problem Settings . . . . . . . . . . . . . . . 210
determination . . . . . . . . . . . 179 Platform-specific variations . . . . . . . . . 211
Overview of fonts . . . . . . . . . . . . 179 z/OS . . . . . . . . . . . . . . . 211
Font specification properties . . . . . . . 179 Windows . . . . . . . . . . . . . . 212
Fonts installed in the system . . . . . . . 179 Linux . . . . . . . . . . . . . . . 212
The font.properties file . . . . . . . . . . 180
The Linux font.properties file . . . . . . . 180 Chapter 24. Using dump agents . . . 213
The Windows font.properties file . . . . . . 181 Help options . . . . . . . . . . . . . 213
Font utilities . . . . . . . . . . . . . . 181 Dump types and triggering . . . . . . . . . 214
Font utilities on Linux, AIX, and z/OS . . . . 181 Types of dump agents - examples . . . . . . 215
Font utilities on Windows systems . . . . . 181 Console dumps . . . . . . . . . . . . 215
Common problems and possible causes . . . . 182 System dumps . . . . . . . . . . . . 215
Tool option . . . . . . . . . . . . . 216
Part 4. Using diagnostic tools . . . 185 Javadumps . . . . . . . . . . . . . 216
Heapdumps . . . . . . . . . . . . . 216
Default dump agents . . . . . . . . . . . 217
Chapter 20. Overview of the available Default settings for dumps . . . . . . . . . 218
diagnostics . . . . . . . . . . . . 187 Limiting dumps using filters . . . . . . . . 218
Categorizing the problem . . . . . . . . . 187 Removing dump agents . . . . . . . . . . 218
Platforms . . . . . . . . . . . . . . . 187
Summary of cross-platform tools . . . . . . . 187 Chapter 25. Using method trace . . . 219
Javadump (or Javacore) . . . . . . . . . 188 Running with method trace . . . . . . . . 219
Heapdump . . . . . . . . . . . . . 188 Examples of use . . . . . . . . . . . . 220
Cross-platform dump formatter . . . . . . 188 Where does the output appear? . . . . . . . 220
JVMPI tools . . . . . . . . . . . . . 188 Advanced options . . . . . . . . . . . . 220
JPDA Tools . . . . . . . . . . . . . 189 Real example . . . . . . . . . . . . . 220
JVM trace . . . . . . . . . . . . . 189
JVMRI . . . . . . . . . . . . . . . 189
Application trace . . . . . . . . . . . 190
Chapter 26. Using the dump formatter 223
Method trace . . . . . . . . . . . . 190 What the dump formatter is . . . . . . . . 223
JVM command-line parameters . . . . . . 190 Problems to tackle with the dump formatter . . . 224
JVM environment variables . . . . . . . . 190 Supported commands . . . . . . . . . . 224
Platform tools . . . . . . . . . . . . . 190 General commands . . . . . . . . . . 224
Commands for analysing the memory . . . . 226
Commands for working with classes . . . . 227
Chapter 21. Using Javadump. . . . . 191 Commands for working with objects . . . . 227
Enabling a Javadump. . . . . . . . . . . 191 Commands for working with Heapdumps. . . 228
The location of the generated Javadump . . . . 191 Commands for working with trace . . . . . 229
Triggering a Javadump . . . . . . . . . . 192 Example session . . . . . . . . . . . . 229
Interpreting a Javadump . . . . . . . . . 192
Javadump tags . . . . . . . . . . . . 193
Locks, monitors, and deadlocks (LOCKS) . . . 193
Chapter 27. JIT problem determination 237
Javadump sample output 1 (z/OS) . . . . . 196 Disabling the JIT . . . . . . . . . . . . 237
Javadump sample output 2 (Linux) . . . . . 202 Selectively disabling the JIT . . . . . . . . 237
Javadump sample output 3 (Windows) . . . . 202 Locating the failing method . . . . . . . . 238
Identifying JIT compilation failures . . . . . . 239
Performance of short-running applications . . . 240
Chapter 22. Using Heapdump . . . . 205
Summary of Heapdump . . . . . . . . . . 205
Information for users of previous releases of
Chapter 28. Garbage Collector
Heapdump . . . . . . . . . . . . . . 205 diagnostics . . . . . . . . . . . . 241
Enabling a Heapdump . . . . . . . . . . 205 How does the Garbage Collector work? . . . . 241
Explicit generation of a Heapdump . . . . . 206 Common causes of perceived leaks . . . . . . 241
Triggered generation of a Heapdump . . . . 206 Listeners . . . . . . . . . . . . . . 241
Enabling text formatted (″classic″) Heapdumps 207 Hash tables . . . . . . . . . . . . . 242
Location of the generated Heapdump . . . . . 207 Static data . . . . . . . . . . . . . 242
Producing a Heapdump using jdmpview . . . . 207 JNI references . . . . . . . . . . . . 242
Available tools for processing Heapdumps . . . 208 Premature expectation . . . . . . . . . 242
vi Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
contents
Contents vii
contents
Changing the trace on a running server . . . . 316 z/OS environment variables . . . . . . . . 326
Selecting ORB traces . . . . . . . . . . . 316
Appendix F. Command-line options 329
Appendix C. CORBA GIOP message Specifying command-line options. . . . . . . 329
format . . . . . . . . . . . . . . 317 General command-line options . . . . . . . 329
GIOP header . . . . . . . . . . . . . 317 System property command-line options . . . . 330
Request header . . . . . . . . . . . . . 318 Nonstandard command-line options . . . . . . 331
Request body . . . . . . . . . . . . . 318 JIT command-line options . . . . . . . . . 333
Reply header . . . . . . . . . . . . . 318 Garbage Collector command-line options . . . . 334
Reply body (based on reply status) . . . . . . 319 General Garbage Collection options . . . . . 334
Cancel request header . . . . . . . . . . 319 Scavenger options . . . . . . . . . . . 336
Locate request header . . . . . . . . . . 319 Compact options . . . . . . . . . . . 336
Locate reply header . . . . . . . . . . . 320 Concurrent options . . . . . . . . . . 336
Locate reply body . . . . . . . . . . . . 320 Trace GC options . . . . . . . . . . . 336
Fragment message . . . . . . . . . . . . 320
Fragment header (GIOP 1.2 only) . . . . . . . 320 Appendix G. Default settings for the
JVM . . . . . . . . . . . . . . . 339
Appendix D. CORBA minor codes . . 321
Appendix H. Notices . . . . . . . . 341
Appendix E. Environment variables 323 Trademarks . . . . . . . . . . . . . . 342
Displaying the current environment . . . . . . 323
Setting an environment variable . . . . . . . 323 Index . . . . . . . . . . . . . . . 345
Separating values in a list . . . . . . . . . 323
JVM environment settings . . . . . . . . . 323
viii Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Figures
1. The components of a typical Java Application 6. Thread stack pointing to an object so that the
Stack and the IBM JRE . . . . . . . . . 4 Garbage Collector can see the object . . . . 62
2. Subcomponent structure of the IBM Virtual 7. Thread stack not pointing to an object so that
Machine for Java . . . . . . . . . . . 5 the Garbage Collector cannot see the object . . 62
3. The ORB client side . . . . . . . . . . 43 8. The AIX 32–Bit Memory Model with
4. Relationship between the ORB, the object MAXDATA=0 (default) . . . . . . . . 112
adapter, the skeleton, and the object 9. Screenshot of the ReportEnv tool . . . . . 144
implementation . . . . . . . . . . . 49 10. Diagram of the DTFJ interface . . . . . . 306
5. Simple portable object adapter architecture 51
Note that although this book covers Windows AMD64. this platform is available
only internally to IBM for testing purposes.
The JRE provides runtime support for Java applications. The SDK provides the
Java compiler and other development tools. The SDK includes the JRE.
The JRE (and, therefore, the SDK) includes a Java Virtual Machine (JVM). This is
the application that executes a Java program. A Java program requires a JVM to
run on a particular platform, such as Linux™, z/OS®, or Windows®.
The IBM SDK, Version 1.4.2 on z/OS 64 and AMD64 platforms, contains a different
implementation of the JVM and the Just-In-Time compiler (JIT) from releases of the
IBM SDK on other platforms (such as 31-bit z/OS, or 32-bit Intel). You can identify
this implementation from the string “IBM J9SE VM” in the output from the java
-version command. For diagnostics information on other IBM SDKs, see
http://www-106.ibm.com/developerworks/java/jdk/diagnosis/.
This book describes problem determination and diagnostics for the JVM.
Check the full version of your installed JVM. If you do not know how to do this,
see Chapter 12, “First steps in problem determination,” on page 91. Some of the
diagnostic tools described in this book apply only to this version or later.
v As an overview of how the IBM Virtual Machine for Java operates, with
emphasis on the interaction with Java. Part 1 of the book provides this
information. You might find this information helpful when you are designing
your application.
v As straightforward guide to determining a problem type, collecting the
necessary diagnostic data, and sending it to IBM. Part 2 and Part 3 of the book
provide this information.
v As the reference guide to all the diagnostic tools that are available in the IBM
Virtual Machine for Java. This information is given in Part 4 of the book.
The parts overlap in some ways. For example, Part 3 refers to chapters that are in
Part 4 when those chapters describe the diagnostics data that is required. You will
be able to more easily understand some of the diagnostics that are in Part 4 if you
read the appropriate chapter in Part 1.
http://www.ibm.com/developerworks/java/
v For Java documentation, see:
http://java.sun.com/products/jdk/1.4/docs/index.html
v For the IBM Java SDKs, see IBM Java downloads at:
http://www.ibm.com/developerworks/java/jdk/index.html
xiv Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
conventions and terminology
v QueryJavaVM()
Options shown with values in braces signify that one of the values must be
chosen. For example:
Options shown with values in brackets signify that the values are optional. For
example:
-Xrunhprof[:help][:<suboption>=<value>,...]
Do not use this method for sending in bug reports on the JVM. For these, use the
usual methods, as described in Part 2, “Submitting problem reports,” on page 75.
Summary of changes
For the August 2006 edition (SC34-6359-06) of this book, minor changes have been
made.
For the April 2006 edition (SC34-6359-05) of this book, minor changes have been
made.
For the January 2006 edition (SC34-6359-04) of this book, the following changes
have been made:
v A new chapter, Chapter 33, “Using DTFJ,” on page 303
For the September 2005 edition (SC34-6359-03) of this book, the following changes
have been made:
v Further changes to Chapter 22, “Using Heapdump,” on page 205.
For the June 2005 edition (SC34-6359-02) of this book the following changes were
made:
v Inclusion of the items in the addenda file.
v Major changes to Chapter 22, “Using Heapdump,” on page 205.
For the January 2005 update to this book, the information about jdkiv has been
removed from Chapter 17, “z/OS problem determination,” on page 151.
xvi Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Part 1. Understanding the IBM Virtual Machine for Java
The information in this part of the book will give you a basic understanding of the
JVM. It provides:
v Background information to explain why some diagnostics work the way they do
v Useful information for application designers
v An explanation of some parts of the JVM
A fairly large amount of information about the garbage collector is provided,
because the garbage collector often seems to be the most difficult part of the JVM
to understand.
Other sections provide a summary, especially where guidelines about the use of
the JVM are appropriate. This part is not intended as a description of the design of
the JVM, except that it might influence application design or promote an
understanding of why things are done the way that they are.
This part also provides a chapter that describes the IBM Object Request Broker
(ORB) component. The IBM ORB ships with the JVM and is used by the IBM
WebSphere® Application Server. It is one of the enterprise features of the Java 2
Standard Edition. The ORB is a tool and runtime component that provides
distributed computing through the OMG-defined CORBA IIOP communication
protocol. The ORB runtime consists of a Java implementation of a CORBA ORB.
The ORB toolkit provides APIs and tools for both the RMI programming model
and the IDL programming model.
The JVM specification also defines several other runtime characteristics. All JVMs :
v Must conform to the same format of runtime files
v Provide fundamental runtime security such as bytecode verification
v Provide intrinsic operations such as performing arithmetic and allocating new
objects
JVMs that implement the specification completely and correctly are called
″compliant″. The IBM Virtual Machine for Java is certified as compliant. However,
not all compliant JVMs are identical. JVM implementers have a wide degree of
freedom to define characteristics of the JVM that are beyond the scope of the
specification. For example, implementers might choose to favour performance or
memory footprint; they might design the JVM for rapid deployment on new
platforms or for various degrees of serviceability. All the JVMs that are currently
used commercially come with a supplementary compiler that takes bytecodes and
outputs platform-dependent machine-code. This compilers works in conjunction
with the JVM to select parts of the Java program that would benefit from the
compilation of bytecode, and replaces the JVM’s virtualized interpretation of these
areas of bytecode with concrete code. This is called ″just-in-time compilation″ (JIT).
IBM’s JIT compiler is described in Chapter 4, “Understanding the JIT,” on page 29.
The IBM Virtual Machine for Java contains a number of private and proprietary
technologies that distinguish it from other implementations of the JVM. In this
release, IBM has made a significant change to the JVM and JIT compiler that were
provided in earlier releases, while retaining full Java compliance. When you read
this Diagnostics Guide, bear in mind that the particular unspecified behavior of
this release of the JVM might be different to the behavior that you experienced in
previous releases. Java programmers should not rely on the unspecified behavior
of a particular JRE for this reason.
Java Application
Java Code
Java Class
Extensions
Class Libraries ORB
Native Libraries
Native Code
NativeOpt. User
IBM JVM Packages Native
Exts.
Others
Platform
Figure 1. The components of a typical Java Application Stack and the IBM JRE
A Java application uses the Java class libraries that are provided by the JRE to
implement the application-specific logic. The class libraries, in turn, are
implemented in terms of other class libraries and, eventually, in terms of primitive
native operations that are provided directly by the JVM. In addition, some
applications must access native code directly.
The JVM facilitates the invocation of native functions by Java applications and a
number of well-defined Java Native Interface functions for manipulating Java from
native code (for more information, see Chapter 6, “Understanding the Java Native
Interface (JNI),” on page 57).
Figure 2 on page 5 shows subcomponent structure of the IBM Virtual Machine for
Java.
4 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JVM API
JVM API
Platform interface
JVM API
The JVM API encapsulates all the interaction between external programs and the
JVM. Examples include:
v Creation and initialization of the JVM through the invocation APIs.
v Interaction with the standard Java launchers, including handling command-line
directives.
v Presentation of public JVM APIs such as JNI, JVMDI, JVMPI, and so on.
v Presentation and implementation of private JVM APIs used by core Java classes.
Diagnostics component
The diagnostics component provides Reliability, Availability, and Serviceability
(RAS) facilities to the JVM.
The IBM Virtual Machine for Java is distinguished by its extensive RAS
capabilities. The IBM Virtual Machine for Java is designed to be deployed in
business-critical operations and includes several trace and debug utilities to assist
with problem determination.
If a problem occurs in the field, IBM’s service engineers can use the capabilities of
the diagnostics component to trace the runtime function of the JVM and identify
the cause of the problem. The diagnostics component can produce output
selectively from various parts of the JVM and the JIT. Part 4, “Using diagnostic
tools,” on page 185 describes various uses of the diagnostics component.
Memory management
The memory management subcomponent is responsible for the efficient use of
system memory by a Java application.
Chapter 1. The building blocks of the IBM Virtual Machine for Java 5
Memory management
storage, the memory management subcomponent must recognize that the storage
is unused and reclaim the memory for subsequent reuse by the application or
return it to the operating system.
The memory management subcomponent has several policy options that you can
specify when you deploy the application. Chapter 2, “Understanding the Garbage
Collector,” on page 7 discusses memory management in the IBM Virtual Machine
for Java.
Class loader
The class loader subcomponent is responsible for supporting Java’s dynamic code
loading facilities, including:
v Reading standard Java .class files.
v Resolving class definitions in the context of the current runtime environment.
v Verifying the bytecodes defined by the class file to determine whether the
bytecodes are language-legal.
v Initializing the class definition after it is accepted into the managed runtime
environment.
v Various reflection APIs for introspection on the class and its defined members.
Interpreter
The interpreter is the implementation of the stack-based bytecode machine that is
defined in the JVM specification. Each bytecode affects the state of the machine
and, as a whole, the bytecodes define the logic of the application.
The interpreter executes bytecodes on the operand stack, calls native functions,
contains and defines the interface to the JIT compiler, and provides support for
intrinsic operations such as arithmetic and the creation of new instances of Java
classes.
The platform port layer is an abstraction of the native platform functions that are
required by the JVM. Other subcomponents of the JVM are written in terms of the
platform-neutral platform port layer functions. Further porting of the JVM requires
the provision of concrete implementations of the platform port layer facilities
rather than wholesale changes to the JVM code.
6 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 2. Understanding the Garbage Collector
This chapter describes the Garbage Collector under these headings:
v “Overview of garbage collection”
v “Allocation” on page 9
v “Detailed description of garbage collection” on page 10
v “How to do heap sizing” on page 16
v “Interaction of the Garbage Collector with applications” on page 18
v “How to coexist with the Garbage Collector” on page 18
v “Frequently asked questions about the Garbage Collector” on page 21
The Garbage Collector allocates areas of storage in the heap. These areas of storage
define objects and arrays. When allocated, an object continues to be live while a
reference (pointer) to it exists somewhere in the active state of the JVM; therefore
the object is reachable. When an object ceases to be referenced from the active state,
it becomes garbage and can be reclaimed for reuse. When this reclamation occurs,
the Garbage Collector must process a possible finalizer and also ensure that any
internal JVM resources that are associated with the object are returned to the pool
of such resources.
Object allocation
Object allocation is driven by requests from inside the JVM for storage for Java
objects, arrays, or classes. Every allocation nominally requires a heap lock to be
acquired to prevent concurrent thread access. To optimize this allocation, particular
areas of the heap are dedicated to a thread, and that thread can allocate from its
local heap area without the need to lock out other threads. This technique delivers
the best possible allocation performance for small objects. Objects are allocated
directly from a thread local allocation buffer, which the thread has previously
allocated from the heap. A new object is allocated from this cache without the need
to grab the heap lock. All objects less than 512 bytes (768 bytes on 64-bit platforms)
are allocated from the cache. Larger objects are allocated from the cache if they can
be contained in the existing cache. This cache is often referred to as the thread local
heap or TLH.
Reachable objects
The active state of the JVM is made up of the set of stacks that represents the
threads, the statics that are inside Java classes, and the set of local and global JNI
references. All functions that are invoked inside the JVM itself cause a frame on the
thread stack. This information is used to find the roots. These roots are then used to
find references to other objects. This process is repeated until all reachable objects
are found.
Garbage collection
When the JVM cannot allocate an object from the current heap because of lack of
space, a memory allocation fault occurs, and the Garbage Collector is invoked. The
first task of the Garbage Collector is to collect all the garbage that is in the heap.
This process starts when any thread calls the Garbage Collector either indirectly as
a result of allocation failure, or directly by a specific call to System.gc(). The first
step is to acquire exclusive control on the virtual machine to prevent any further
Java operations. Garbage collection can then begin. It occurs in three phases:
v Mark
v Sweep
v Compaction (optional)
Mark phase
In the mark phase, all the objects that are referenced from the thread stacks, statics,
interned strings, and JNI references are identified. This action creates the root set of
objects that the JVM references. Each of those objects might, in turn, reference
others. Therefore, the second part of the process is to scan each object for other
references that it makes. These two processes together generate a bit vector that
defines the beginning of all the live objects.
Sweep phase
The sweep phase uses the mark bit vector generated by the mark phase to identify
the chunks of heap storage that can be reclaimed for future allocations; these
chunks are added to the pool of free space.
Compaction phase
When the garbage has been reclaimed from the heap, the Garbage Collector can
consider compacting the resulting set of objects to remove the spaces that are
between them. Because compaction can take a long time, the Garbage Collector
only compacts when it is absolutely necessary. Compaction is, therefore, a rare
event.
Heap size
The maximum heap size is controlled by the -Xmx option. If this option is not
specified, the default applies as follows:
Windows
Half the real storage with a minimum of 16 MB and a maximum of
2 GB -1.
z/OS 64 MB.
Linux Half the real storage with a minimum of 16 MB and a maximum of
512 MB -1.
The initial size of the heap is controlled by the -Xms option. If this option is not
specified, the default applies as follows:
8 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Heap size
For some applications, the default settings might not give the best results. Listed
here are some problems that might occur, and some suggested actions that you can
take. Use verbosegc to help you monitor the heap.
The frequency of garbage collections is too high until the heap reaches a steady
state.
Use verbosegc to determine the size of the heap at a steady state and set -Xms
to this value.
The heap is fully expanded and the occupancy level is greater than 70%.
Increase the -Xmx value so that the heap is not more than 70% occupied, but
for best performance try to ensure that the heap never pages. The maximum
heap size should, if possible, be able to be contained in physical memory to
avoid paging.
At 70% occupancy the frequency of garbage collections is too great.
Change the setting of -Xminf. The default is 0.3, which tries to maintain 30%
free space by expanding the heap. A setting of 0.4, for example, increases this
free space target to 40%, and reduces the frequency of garbage collections.
Pause times are too long.
Try using -Xgcpolicy:optavgpause. This reduces the pause times and makes
them more consistent when the heap occupancy rises. It does, however, reduce
throughput by approximately 5%, although this value varies with different
applications.
Allocation
The Garbage Collector is the JVM memory manager and is therefore responsible
for allocating memory in addition to collecting garbage. Because the task of
memory allocation is small, compared to that of garbage collection, the term
“garbage collection” usually also means “memory management”.
If the Garbage Collector cannot find a big enough chunk of free storage, allocation
fails and the Garbage Collector must perform a garbage collection. After a garbage
collection cycle, if the Garbage Collector created enough free storage, it searches
the freelist again and picks up a free chunk. If the Garbage Collector does not find
enough free storage, it returns out of memory. The heap lock is released either after
the object has been allocated, or if not enough free space is found.
Cache allocation
Cache allocation is specifically designed to deliver the best possible allocation
performance for small objects. Objects are allocated directly from a thread local
allocation buffer that the thread has previously allocated from the heap. A new
object is allocated from this cache without the need to grab the heap lock;
therefore, cache allocation is very efficient.
All objects less than 512 bytes (768 bytes on 64-bit platforms) are allocated from the
cache. Larger objects are allocated from the cache if they can be contained in the
existing cache; if not a locked heap allocation is performed.
The cache block is sometimes called a thread local heap (TLH). The size of the
TLH varies from 2 KB to 128 KB, depending on the use of the TLH.
Mark phase
In this phase, all the live objects are marked. Because unreachable objects cannot be
identified singly, all the reachable objects must be identified. Therefore, everything
else must be garbage. The process of marking all reachable objects is also known as
tracing.
10 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Mark phase
bytes of heap space on 31- and 32-bit architectures and one bit for each 8 bytes
of heap space on 64-bit architectures. The bit that corresponds to the start
address for each reachable object is set when it is first visited.
The first stage of tracing is the identification of root objects. The active state of the
JVM is made up of the saved registers for each thread, the set of stacks that
represent the threads, the statics that are in Java classes, and the set of local and
global JNI references. All functions that are invoked in the JVM itself cause a frame
on the C stack. This frame might contain references to objects as a result of either
an assignment to a local variable, or a parameter that is sent from the caller. All
these references are treated equally by the tracing routines.
All the mark bits for all root objects are set and references to the roots pushed to
the mark stack. After this is done, tracing can proceed by iteratively popping a
reference off the mark stack and then scanning the referenced object for references
to other objects. If there are any references to unmarked objects, that is, mark bit
off, the object is marked by setting the appropriate bit in the mark bit array and
the reference is pushed to the mark stack. This process continues until all the work
packets are on the empty list, at which point all the reachable (live) objects, have
been identified.
When a marking thread asks for a new non-empty packet and all work packets are
empty, the GC checks the list of overflow classes. If the list is not empty, the GC
traverses this list and repopulates a work packet with the references to the objects
on the overflow lists. These packets are then processed as described above. Tracing
is complete when all the work packets are empty and the overflow list is empty.
Parallel mark
The goal of Parallel Mark is to not degrade Mark performance on a uniprocessor,
and to increase typical Mark performance on a multiprocessor system.
Object marking is increased through the addition of helper threads that share the
use of the pool of work packets; for example, full output packets that are returned
to the pool by one thread can be picked up as new input packets by another
thread. Parallel Mark still requires the participation of one application thread that
is used as the master coordinating agent. This thread performs very much as it
always did, but the helper threads assist both in the identification of the root
pointers for the collection and in the tracing of these roots. Mark bits are updated
by using atomic primitives that require no additional lock.
A platform with N processors also has N-1 new helper threads, that work with the
master thread to complete the marking phase of garbage collection. You can
override the default number of threads by using the -Xgcthreads option. If you
specify a value of 1, there will be no helper threads. The -Xgcthreads option
accepts any value greater than 0, but you gain little by setting it to more than N-1.
Concurrent mark
Concurrent mark gives reduced and consistent garbage collection pause times
when heap sizes increase. It starts a concurrent marking phase before the heap is
full. In the concurrent phase, the Garbage Collector scans the roots by asking each
thread to scan its own stack. These roots are then used to trace live objects
concurrently. Tracing is done by a low-priority background thread and by each
application thread when it does a heap lock allocation.
While the Garbage Collector is marking live objects concurrently with application
threads running, it has to record any changes to objects that are already traced. It
uses a write barrier that is activated every time a reference in an object is updated.
The write barrier flags when an object reference update has occurred, to force a
rescan of part of the heap. The heap is divided into 512-byte sections and each
section is allocated a byte in the card table. Whenever a reference to an object is
updated, the card that corresponds to the start address of the object that has been
updated with the new object reference is marked with 0x01. A byte is used instead
of a bit for two reasons: a write to a byte is quicker than a bit change, and the
other bits are reserved for future use. An STW collection is started when one of the
following occurs:
v An allocation failure
v A System.gc
v Concurrent mark completes all the marking that it can do
The Garbage Collector tries to start the concurrent mark phase so that it completes
at the same time as the heap is exhausted. The Garbage Collector does this by
constant tuning of the parameters that govern the concurrent mark time. In the
STW phase, the Garbage Collector scans all roots, uses the marked cards to see
what must be retraced, then sweeps as normal. It is guaranteed that all objects that
were unreachable at the start of the concurrent phase are collected. It is not
guaranteed that objects that become unreachable during the concurrent phase are
collected.
Reduced and consistent pause times are the benefits of concurrent mark, but they
come at a cost. Application threads must do some tracing when they are requesting
a heap lock allocation. The overhead varies depending on how much idle CPU
time is available for the background thread. Also, the write barrier has an
overhead.
Sweep phase
On completion of the mark phase the mark bit vector identifies the location of all
the live objects in the heap. The sweep phase uses this to identify those chunks of
12 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Sweep phase
heap storage that can be reclaimed for future allocations; these chunks are added
to the pool of free space. To avoid filling this free space pool with lots of small
chunks of storage, only chunks of at least a certain size are reclaimed and added to
the free pool. The minimum size for a free chunk is currently defined as 512 bytes
(768 bytes on 64-bit platforms).
A free chunk is identified by examining the mark bit vector looking for sequences
of zeros, which identify possible free space. GC ignores any sequences of zeroes
that correspond to a length less than the minimum free size. When a sequence of
sufficient length is found, the Garbage Collector checks the length of the object at
the start of the sequence to determine the actual amount of free space that can be
reclaimed. If this amount is greater than or equal to the minimum size for a free
chunk, it is reclaimed and added to the free space pool.
The small areas of storage that are not on the freelist are known as ″dark matter″,
and they are recovered when the objects that are next to them become free, or
when the heap is compacted. It is not necessary to free the individual objects in the
free chunk, because it is known that the whole chunk is free storage. When a
chunk is freed, the Garbage Collector has no knowledge of the objects that were in
it.
Compaction phase
When the garbage has been removed from the heap, the Garbage Collector can
consider compacting the resulting set of objects, to remove the spaces that are
between them. The process of compaction is complicated because if any object is
moved, the Garbage Collector must change all the references that exist to it.
The following analogy might help you understand the compaction process. Think
of the heap as a warehouse that is partly full of pieces of furniture of different
sizes. The free space is the gaps between the furniture. The free list contains only
gaps that are above a particular size. Compaction pushes everything in one
direction and closes all the gaps. It starts with the object that is closest to the wall,
and puts that object against the wall. Then it takes the second object in line and
puts that against the first. Then it takes the third and puts it against the second,
and so on. At the end, all the furniture is at one end of the warehouse and all the
free space is at the other.
To keep compaction times to a minimum, the helper threads are used again.
Compaction occurs if any of the following are true and -Xnocompactgc has not
been specified:
v -Xcompactgc has been specified.
v Following the sweep phase, not enough free space is available to satisfy the
allocation request.
v A System.gc() has been requested and the last allocation failure garbage
collection did not compact.
v At least half the previously available memory has been consumed by TLH
allocations (ensuring an accurate sample) and the average TLH size falls below
1000 bytes.
v Less than 5% of the active heap is free.
v Less than 128 KB of the active heap is free.
Reference objects
When a reference object is created, it is added to a list of reference objects of the
same type. Instances of SoftReference, WeakReference, and PhantomReference are
created by the user and cannot be changed; they cannot be made to refer to objects
other than the object that they referenced on creation. Each reference results in the
creation of a reference object. Objects whose classes define a finalize method result
in a pointer to that object being placed on a list of objects that require finalization.
During garbage collection, immediately following the mark phase, these lists are
processed in a specific order:
1. Soft
2. Weak
3. Final
4. Phantom
If the referent is not marked, GC has a candidate for collection. At this point the
process differs for each reference type. Soft references are collected if their referent
has not been marked for the previous two garbage collection cycles. If there is a
shortage of available storage, all soft references are cleared. Currently this happens
only on System.gc() calls and if an allocation failure could not be satisfied
following a garbage collection.
Phantom references are collected if their referent is not marked or they are no
longer reachable. When a phantom reference is processed, its referent is marked so
it will persist until the following garbage collection cycle or until the phantom
reference is processed if it is associated with a reference queue. When it is
determined that a reference is eligible for collection, it is either queued to its
associated reference queue or simply removed from the reference list.
the object. Then GC removes the element on the unfinalized object list. The final
method for the object is then run at an undetermined point in the future by the
reference handler thread.
Heap expansion
Heap expansion occurs after garbage collection while exclusive access of the virtual
machine is still held. The active part of the heap is expanded up to the maximum
if one of the following is true:
v The Garbage Collector did not free enough storage to satisfy the allocation
request.
v Free space is less than the minimum free space, which you can set by using the
-Xminf parameter. The default is 30%.
v More than 13% of the time is being spent in garbage collection.
Heap shrinkage
Heap shrinkage occurs after garbage collection while exclusive access of the virtual
machine is still held. Shrinkage does not occur if any of the following are true:
v The Garbage Collector did not free enough space to satisfy the allocation
request.
v The maximum free space, which can be set by the -Xmaxf parameter (default is
60%), is set to 100%.
v The heap has been expanded in the last three garbage collections.
v This is a System.gc() and the amount of free space at the beginning of the
garbage collection was less than -Xminf (default is 30%) of the live part of the
heap.
v If none of the above is true and more than -Xmaxf free space exists, the Garbage
Collector must calculate how much to shrink the heap to get it to -Xmaxf free
space, without going below the initial (-Xms) value. This figure is rounded
down to a 256-byte boundary (512 bytes if Concurrent mark is used) on 32-bit
architecture, or a 1024 bytes boundary on 64-bit architecture.
A compaction occurs before the shrink if all the following are true:
v A compaction was not done on this garbage collection cycle.
v No free chunk is at the end of the heap, or the size of the free chunk that is at
the end of the heap is less than 10% of the required shrinkage amount.
v The Garbage Collector did not shrink and compact on the last garbage collection
cycle.
Note that, on initialization, the JVM allocates the whole heap in a single
contiguous area of virtual storage. The amount that is allocated is determined by
the setting of the -Xmx parameter. No virtual space from the heap is ever freed
back to the native operating system. When the heap shrinks, it shrinks inside the
original virtual space.
Whether any physical memory is released depends on the ability of the native
operating system. If it supports paging; that is, the ability of the native operating
system to commit and decommit physical storage to the virtual storage, the
Garbage Collector uses this function. In this case, physical memory can be
decommitted on a heap shrinkage.
To summarize. You never see the amount of virtual memory that is used by the
JVM decrease. You might see physical memory free size increase after a heap
shrinkage. The native operating system determines what it does with decommitted
pages.
Also note that, where paging is supported, the Garbage Collector allocates physical
memory to the initial heap to the amount that is specified by the -Xms parameter.
Additional memory is committed as the heap grows.
16 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
How to do heap sizing
Collector runs, therefore, becomes a very expensive operation. Also, the heap is
most likely to be very fragmented when a need to do a heap compaction occurs.
Again, this is a very expensive operation. The recommendation is to start your
application with the minimum heap size that it needs. When it starts up, the
Garbage Collector will run often and, because the heap is small, efficiently.
Therefore, an application normally runs until the heap is full. Then, successive
garbage collection cycles recover garbage. When the heap is full of live objects, the
Garbage Collector compacts the heap. If and when the heap is full of live objects
and cannot be compacted, the Garbage Collector expands the heap size.
From the above description, you can see that the Garbage Collector compacts the
heap as the needs of the application rise, so that as the heap expands, it expands
with a set of compacted objects in the bottom of the original heap. This is an
efficient way to manage the heap, because compaction runs on the
smallest-possible heap size at the time that compaction is found to be necessary.
Compaction is performed with the minimum heap sizes as the heap grows. Some
evidence exists that an application’s initial set of objects tends to be the key or root
set, so that compacting them early frees the remainder of the heap for more
short-lived objects.
Eventually, the JVM has the heap at maximum size with all long-lived objects
compacted at the bottom of the heap. The compaction occurred when compaction
was in its least expensive phase. The overheads of expanding the heap are almost
trivial compared to the cost of collecting and compacting a very large fragmented
heap.
Using verbosegc
The verbosegc output is fully described in Chapter 28, “Garbage Collector
diagnostics,” on page 241. Switch on verbosegc and run up the application with no
load. Check the heap size at this stage. This provides a rough guide to the start
size of the heap (-Xms option) that is needed. If this value is much larger than the
defaults (see Appendix G, “Default settings for the JVM,” on page 339), think about
reducing this value a little to get efficient and rapid compaction up to this value,
as described in “Initial and maximum heap sizes” on page 16.
By running an application under stress, you can determine a maximum heap size.
Use this to set your max heap (-Xmx) value.
-Xmaxe
-Xmine
-Xmaxf
-Xminf
Note clause 4b. The specification says that a manual invocation of the Garbage
Collector (for example, through the System.gc() call) suggests that a garbage
collection cycle might be run. In fact, the call is interpreted as “Do a full garbage
collection scan unless a garbage collection cycle is already executing”.
Root set
Consider the root set. It is mainly a pseudo-random set of references from what
happened to be in the stacks and registers of the JVM threads at the time that the
Garbage Collector was invoked. This means that the graph of reachable objects that
the Garbage Collector constructs in any given cycle is nearly always different from
that traced in another cycle. (See clause 5). This has significant consequences for
finalizers (clause 7), which are described more fully in “Finalizers” on page 19.
18 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
How to coexist with the Garbage Collector
efficient. When a cache becomes full, a thread returns the TLH to the main heap
and grabs another chunk for a new cache.
Bug reports
Attempts to predict the behavior of the Garbage Collector are frequent underlying
causes of bug reports. An example of a regular bug report to Java service of the
hello-world variety is one in which a simple programme allocates some object or
objects, clears references to these objects, then initiates a garbage collection cycle.
The objects are not seen as collected, usually because the application has attached a
finalizer that reports when it is run.
It should be clear from the contract and the unpredictable nature of the Garbage
Collector that more than one valid reason exists for this:
v An object reference exists in the thread stack or registers, and the objects are
retained garbage.
v The Garbage Collector has not chosen to run a finalizer cycle at this time.
See clause 1 on page 18. True garbage is always found eventually, but it is not
possible to predict when (clause 5 on page 18).
Finalizers
The Java service team strongly recommends that applications avoid the use of
finalizers as far as possible. The JVM specification states that finalizers should be
used as an emergency clear-up of, for example, hardware resources. The service
team recommends that this should be the only use of finalizers. They should not
be used to clean up Java software resources or for closedown processing of
transactions.
The reasons for this recommendation are partly in the nature of finalizers and how
they are permanently linked to garbage collection, and partly in the contract that is
described in “Interaction of the Garbage Collector with applications” on page 18.
These topics are examine more closely in the following sections.
Nature of finalizers
The JVM specification says nothing about finalizers, except that they are final in
nature. Nothing states when, how, or even whether a finalizer is run. The only rule
is that if and when it is run, it is final.
Final, in terms of a finalizer, means that the class object is known not to be in use
any more. Clearly, this can happen only when the object is not reachable. Only the
Garbage Collector can determine this. Therefore, when the Garbage Collector runs,
it determines which are the unreachable objects that have a finalizer method.
Normally, such objects would be collected, and the Garbage Collector would be
able to satisfy the memory allocation fault. Finalized garbage, however, must have
its finalizer run before it can be collected. Therefore, no finalized garbage can be
collected in the cycle that actually finds it. Finalizers therefore make a garbage
collection cycle longer (the cycle has to detect and process the objects) and less
productive. Finalizers are an overhead on garbage collection. Because garbage
collection is a stop-the-world operation, it makes sense to reduce this overhead as
far as possible.
Note that the Garbage Collector cannot run finalizers itself when it finds them.
This is because a finalizer might run an operation that takes a long time, and the
Garbage Collector cannot risk locking out the application while this operation is
running. So finalizers must be collected into a separate thread for processing. This
task adds more overhead into the garbage collection cycle.
Summary
v Finalizers are an expensive overhead.
v Finalizers are not dependable.
For tidying Java resources, think about the use of a clean up routine. When you
have finished with an object, call the routine to null out all references, deregister
listeners, clear out hash tables, and so on. This is far more efficient than using a
finalizer and has the useful side-benefit of speeding up garbage collection. The
Garbage Collector does not have so many object references to chase in the next
garbage collection cycle.
Manual invocation
The Garbage Collector contract subclause 4b on page 18 notes that the Garbage
Collector always honors a manual invocation; for example, through the System.gc
() call. This call nearly always invokes a garbage collection cycle, which is
expensive.
20 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
How to coexist with the Garbage Collector
The Java service team recommend that this call is not used, or if it is, it is
enveloped in conditional statements that block its use in an application runtime
environment. The Garbage Collector is carefully adjusted to deliver maximum
performance to the JVM. Forcing it to run severely degrades JVM performance
From the previous sections, you can see that it is pointless trying to force the
Garbage Collector to do something predictable, such as collecting your new
garbage or running a finalizer. It might happen; it might not. Let the Garbage
Collector run in the parameters that an application selects at start-up time. This
method nearly always produces best performance.
Summary
Do not try to control the Garbage Collector or to predict what will happen in a
given garbage collection cycle. You cannot do it. This unpredictability is handled,
and the Garbage Collector is designed to run well and efficiently inside these
conditions. Set up the initial conditions that you want and let the Garbage
Collector run. It will honor the contract (described in “Interaction of the Garbage
Collector with applications” on page 18), which is within the JVM specification.
You can control the number of GC helper threads with the -Xgcthreads option.
Passing the -Xgcthreads1 option to Java results in no helper threads at all.
You gain little by setting -Xgcthreads to more than n-1 other than possibly
alleviating mark-stack overflows, if you suffer from them.
How can I prevent Java heap fragmentation?
Note that the following suggestions might not help avoid fragmentation in all
cases.
v Start with a small heap. Set -Xms far lower than -Xmx. It might be
appropriate to allow -Xms to default, because the default is a low value.
v Increase the maximum heap size, -Xmx.
v If the application uses JNI, make sure JNI references are properly cleared. All
objects being referenced by JNI are pinned and not moved during
compaction, contributing significantly to heap fragmentation.
What is Mark Stack Overflow? Why is MSO bad for performance?
Mark stacks are used for tracing all object reference chains from the roots. Each
such reference that is found is pushed onto the mark stack so that it can be
traced later. Mark stacks are of fixed size, so they can overflow. This situation
is called Mark Stack Overflow (MSO). The algorithms to handle this situation
are very expensive in processing terms, and so MSO is a big hit on GC
performance.
How can I prevent Mark Stack Overflow?
There is nothing an application can do to avoid MSO, except to reduce the
number of objects it allocates. The following suggestions are not guaranteed to
avoid MSO:
v Increase the number of GC helper threads using -Xgcthreads command-line
option
v Decrease the size of the Java heap using the -Xmx setting.
v Use a small initial value for the heap or use the default.
When and why does the Java heap expand?
The JVM starts with a small default Java heap, and it expands the heap based
on an application’s allocation requests until it reaches the value specified by
-Xmx. Expansion occurs after GC if GC is unable to free enough heap storage
for an allocation request, or if the JVM determines that expanding the heap is
required for better performance.
When does the Java heap shrink?
Heap shrinkage occurs when GC determines that there is a lot of free heap
storage, and releasing some heap memory is beneficial for system performance.
Heap shrinkage occurs after GC, but when all the threads are still suspended.
Does the IBM GC guarantee that it will clear all the unreachable objects?
The IBM GC guarantees only that all the objects that were not reachable at the
beginning of the mark phase will be collected. While running concurrently, our
GC guarantees only that all the objects that were unreachable when concurrent
mark began will be collected. Some objects might become unreachable during
concurrent mark, but they are not guaranteed to be collected.
I am getting an OutOfMemoryError. Does this mean that the Java heap is
exhausted?
Not necessarily. Sometimes the Java heap has free space but an
OutOfMemoryError can occur. The error could occur because of
v Shortage of memory for other operations of the JVM.
22 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Frequently asked questions about the Garbage Collector
24 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 3. Understanding the class loader
The Java 2 JVM introduced a new class loading mechanism with a
parent-delegation model. The parent-delegation architecture to class loading was
implemented to aid security and to help programmers to write custom class
loaders.
The class loader loads, verifies, prepares and resolves, and initializes a class from a
JVM class file.
v Loading involves obtaining the byte array representing the Java class file.
v Verification of a JVM class file is the process of checking that the class file is
structurally well-formed and then inspecting the class file contents to ensure that
the code does not attempt to perform operations that are not permitted.
v Preparation involves the allocation and default initialization of storage space for
static class fields. Preparation also creates method tables, which speed up virtual
method calls, and object templates, which speed up object creation.
v Initialization involves the execution of the class’s class initialization method, if
defined, at which time static class fields are initialized to their user-defined
initial values (if specified).
Symbolic references within a JVM class file, such as to classes or object fields that
reference a field’s value, are resolved at runtime to direct references only. This
resolution might occur either:
v After preparation but before initialization
v Or, more typically, at some point following initialization, but before the first
reference to that symbol.
The delay is generally to increase execution speed. Not all symbols in a class file
are referenced during execution. So, by delaying resolution, fewer symbols might
have to be resolved, giving you less runtime overhead. Additionally, the cost of
resolution is gradually reduced over the total execution time.
The JVM has three class loaders, each possessing a different scope from which it
can load classes. As you descend the hierarchy, the scope of available class
repositories widens, and normally the repositories are less trusted:
Bootstrap
|
Extensions
|
Application
At the top of the hierarchy is the bootstrap class loader. This class loader is
responsible for loading only the classes that are from the core Java API. These are
the most trusted classes and are used to bootstrap the JVM.
The extensions class loader can load classes that are standard extensions packages
in the extensions directory.
The application class loader can load classes from the local file system, and will
load files from the CLASSPATH. The application class loader is the parent of any
custom class loader or hierarchy of custom class loaders.
Because class loading is always delegated first to the parent of the class loading
hierarchy, the most trusted repository (the core API) is checked first, followed by
the standard extensions, then the local files that are on the class path. Finally,
classes that are located in any repository that your own class loader can access, are
accessible. This system prevents code from less-trusted sources from replacing
trusted core API classes by assuming the same name as part of the core API.
A name space is a set of class names that are loaded by a specific class loader.
When an entry for a class has been added into a name space, it is impossible to
load another class of the same name into that name space. Multiple copies of any
given class can be loaded because a name space is created for each class loader.
You can grant special access privileges between classes that are in the same
package by the use of package or protected access. This gives access rights
between classes of the same package, but only if they were loaded by the same
class loader. This stops code from an untrusted source trying to insert a class into a
trusted package. As discussed above, the delegation model prevents the possibility
of replacing a trusted class with a class of the same name from an untrusted
source. The use of name spaces prevents the possibility of using the special access
privileges that are given to classes of the same package to insert code into a
trusted package.
26 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Why write your own class loader?
The Java 2 class loading system has simplified the process for creating custom class
loaders. The ClassLoader class was given a new constructor that takes the parent
class loader as a parameter. This parent class loader can be either the application
class loader, or another user-defined class loader. This allows any user-defined
class loader to be contained easily into the delegation model.
Under the delegation model, the loadClass() method is no longer abstract, and as
such does not need to be overridden. The loadClass() method handles the
delegation class loader mechanism and should not be overridden, although it is
possible to do so, so that Java 1 style ClassLoaders can run on a Java 2 JVM.
28 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 4. Understanding the JIT
The Just-In-Time compiler (JIT) is not part of the JVM, but is a basic component of
the SDK. This chapter summarizes the relationship between the JVM and the JIT,
and gives a short description of how the JIT works.
JIT overview
Java is an interpreted language, so it has a Write Once Run Anywhere (WORA)
capability. The Java compiler reads Java source files and outputs strings of
bytecodes, which are platform-neutral pseudo-machine code. At runtime, the JVM
reads these bytecodes, interprets the semantics of each individual bytecode, and
performs the appropriate computation. This means that a JVM that is interpreting
bytecodes has a slower performance than a native application consisting of
machine code generated by a native compiler.
The JIT is therefore important because it helps improve the performance of Java
applications. The JIT comes into use whenever a Java method is called; it compiles
the bytecodes of that method into native machine code, compiling it ″just in time″
to execute. After a method is compiled, the JVM calls that the compiled code of
that method directly instead of interpreting it. However, when the JVM starts,
thousands of methods are executed. There is a significant overhead on all the
methods because of the time it takes the JIT to run and compile them. This means
that if you run without the JIT, the JVM starts up quickly but runs slowly.
Conversely, if you run with the JIT, the JVM starts up slowly, then runs quickly. In
some applications, you might find that it takes longer to start the JVM than to run
the application itself.
In practice, not all methods are compiled the first time they are called. For each
method, the JVM maintains a call count, which is incremented every time the
method is invoked. The JVM interprets a method until its call count exceeds a JIT
threshold. Therefore, often-used methods are compiled soon after the JVM has
started; conversely, the methods that are used less often are compiled much later
or perhaps not at all. In fact, the compilation of methods is spread out over the life
of the JVM. This way, the JVM starts up quickly, but the program does not suffer
performance loss because methods are compiled to native code when their call
counts reach the JIT threshold. The threshold is carefully selected to obtain the
maximum balance between startup times and run-time performance.
After a method is compiled, its call count is reset to zero; subsequent calls to the
method continue to increment its count. When the call count of a method reaches a
JIT recompilation threshold, it is compiled a second time, this time applying a larger
selection of optimizations than on the previous compilation (because the method
has proven to be a significant part of the whole program). The recompilation
process is iterative; the call count of a recompiled method is reset again and, as it
reaches succeeding thresholds, triggers recompilations at increasing optimization
levels. Thus, the busiest methods of a Java program are always optimized most
aggressively, maximizing the performance benefits of using the JIT. The JIT can
also measure operational data at run time, and use that data to improve the quality
of further recompilations.
1) Inlining
Inlining is the process by which the trees of smaller methods are merged, or
″inlined″, into the trees of their callers. This speeds up frequently executed method
calls. Two inlining algorithms with different levels of aggressiveness are used,
depending on the current optimization level. Optimizations performed in this
phase include:
v Trivial inlining
v Call graph inlining
v Tail recursion elimination
v Virtual call guard optimizations
2) Local optimizations
Local optimizations analyze and improve a small section of the code at a time.
Many local optimizations implement tried and tested techniques used in classic
static compilers. The optimizations include:
v Local data flow analysis and optimizations
v Register usage optimization
v Simplifications of Java idioms
These techniques are applied repeatedly, especially after global optimizations,
which might have pointed out more opportunities for improvement.
30 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
How the JIT optimizes code
v Exception-directed optimization
v Switch analysis
4) Global optimizations
Global optimizations work on the entire method at once. They are more
″expensive″, requiring larger amounts of compilation time, but can provide a great
increase in performance:
v Global data flow analyses and optimizations
v Partial redundancy elimination
v Escape analysis
v GC and memory allocation optimizations
v Synchronization optimizations
Therefore, if a Java program crashes or hangs in the JVM process space, but
outside the range of the JVM executable code in that process, the problem is likely
to be within the code cache.
32 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 5. Understanding the ORB
This chapter describes the Object Request Broker (ORB). The topics are:
v “CORBA”
v “RMI and RMI-IIOP”
v “Java IDL or RMI-IIOP?” on page 34
v “RMI-IIOP limitations” on page 34
v “Further reading” on page 34
v “Examples of client–server applications” on page 34
v “Using the ORB” on page 40
v “How the ORB works” on page 43
v “Features of the ORB” on page 49
CORBA
Common Object Request Broker Architecture (CORBA) is an open,
vendor-independent specification for distributed computing. It is published by the
Object Management Group (OMG). Using the Internet Inter-ORB Protocol (IIOP), it
allows objects on different architectures, operating systems, and networks to
interoperate. This interoperability is obtained by the use of the Interface Definition
Language (IDL), which specifies the syntax that is used to invoke operations on
objects. IDL is programming-language independent.
Developers define the hierarchy, attributes, and operations of objects in IDL, then
use an IDL compiler (such as IDLJ for Java) to map the definition onto an
implementation in a programming language. The implementation of an object is
encapsulated. Clients of the object can see only its external IDL interface.
OMG have produced specifications for mappings from IDL to many common
programming languages, including C, C++, and Java. Central to the CORBA
specification is the Object Request Broker (ORB). The ORB routes requests from
client to remote object, and responses to their destinations. Java contains an
implementation of the ORB that communicates by using IIOP.
RMI-IIOP is an extension of traditional Java RMI that uses the IIOP protocol. This
protocol allows RMI objects to communicate with CORBA objects. Java programs
can therefore interoperate transparently with objects that are written in other
programming languages, provided that those objects are CORBA-compliant.
Objects can still be exported to traditional RMI (JRMP) however, and the two
protocols can communicate.
A terminology difference exists between the two protocols. In RMI (JRMP), the
server objects are called skeletons; in RMI-IIOP, they are called ties. Client objects
are called stubs in both protocols.
RMI-IIOP limitations
In a Java-only application, RMI (JRMP) is more lightweight and efficient than
RMI-IIOP is, but less scalable. Because it has to conform to the CORBA
specification for interoperability, RMI-IIOP is a more complex protocol. The
developing of an RMI-IIOP application is much more similar to CORBA than it is
to RMI (JRMP).
You must take care if you try to deploy an existing CORBA application in a Java
RMI-IIOP environment. An RMI-IIOP client cannot necessarily access every
existing CORBA object. The semantics of CORBA objects that are defined in IDL
are a superset of those of RMI-IIOP objects. That is why the IDL of an existing
CORBA object cannot always be mapped into an RMI-IIOP Java interface. It is only
when the semantics of a specific CORBA object are designed to relate to those of
RMI-IIOP that an RMI-IIOP client can call a CORBA object.
Further reading
Object Management Group website: http://www.omg.org contains CORBA
specifications that are available to download.
You can find the RMI-IIOP Programmer’s Guide in your SDK installation directory
under docs/rmi-iiop/rmi_iiop_pg.html. Example programs are provided in
demo/rmi-iiop.
Interfaces
These are the interfaces that are to be implemented:
v CORBA IDL Interface (Foo.idl):
interface Foo { string message(); };
v JAVA RMI Interface (Foo.java):
34 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Examples of client–server applications
These two interfaces define the characteristics of the remote object. The remote
object implements a method, named message, that does not need any parameter,
and it returns a string. For further information about IDL and its mapping to Java
see, the OMG specifications (www.omg.org).
In the early versions of Java RMI (JRMP), the servant class had to extend the
java.rmi.server.UnicastRemoteObject class. Now, you can use the class
PortableRemoteObject for both RMI over JRMP and IIOP, thereby making the
development of the remote object virtually independent of the protocol that is
used. Also, the object implementation does not need to extend
PortableRemoteObject, especially if it already extends another class (single-class
inheritance). However, in this case, the remote object instance must be exported in
the server implementation (see below). By exporting a remote object, you make
that object available to accept incoming remote method requests. When you extend
javax.rmi.PortableRemoteObject, your class is exported automatically on creation.
The CORBA or Java IDL implementation of the remote object (servant) is:
public class FooImpl extends _FooPOA {
public String message() { return "Hello World"; }
}
The compilation generates the files that are shown in Table 2 on page 36. (Use the
-keep option with rmic if you want to keep the intermediate .java files).
In the J2SE v.1.4 ORB, the default object adapter (see the OMG CORBA
specification v.2.3) is the portable object adapter (POA). Therefore, the default
skeletons and ties that the IDL compiler generates can be used by a server that is
using the POA model and interfaces. By using the idlj -oldImplBase option, you
can still generate older versions of the server-side skeletons that are compatible
with servers that are written in J2SE 1.3 and earlier.
Server code
The server application has to create an instance of the remote object and publish it
in a naming service. The Java Naming and Directory Interface (JNDI) defines a set
of standard interfaces that are used to query a naming service or to bind an object
to that service.
However, to tell the application which naming implementation is in use, you must
set one of the following Java properties:
v java.naming.factory.initial: Defined also as
javax.naming.Context.INITIAL_CONTEXT_FACTORY, this property specifies the
class name of the initial context factory for the naming service provider. For RMI
registry, the class name is com.sun.jndi.rmi.registry.RegistryContextFactory. For
the CosNaming Service, the class name is com.sun.jndi.cosnaming.CNCtxFactory.
v java.naming.provider.url: This property configures the root naming context, the
ORB, or both. It is used when the naming service is stored in a different host,
and it can take several URI schemes:
– rmi
– corbaname
– corbaloc
36 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Examples of client–server applications
– IOR
– iiop
– iiopname
For example:
rmi://[<host>[:<port>]][/<initial_context>] for RMI registry
iiop://[<host>[:<port>]][/<cosnaming_name>] for COSNaming
For example, with RMI(JRMP), you do not need to do much other than create an
instance of the servant and follow the previous steps to bind this reference in the
naming service.
With CORBA (Java IDL), however, you must do some extra work because you
have to create an ORB. The ORB has to make the servant reference available for
remote calls. This mechanism is usually controlled by the object adapter of the
ORB.
public class Server {
public static void main (String args []) {
try {
ORB orb = ORB.init(args, null);
// bind the object reference ref to the naming service using JNDI
..........(see previous code) .....
orb.run();
}
catch(Exception e) {}
}
}
For RMI-IIOP:
public class Server {
public static void main (String args []) {
try {
ORB orb = ORB.init(args, null);
// bind the object reference ref to the naming service using JNDI
..........(see previous code) .....
}
catch(Exception e) {}
}
}
To use the previous POA server code, you must use the -iiop -poa options together
to enable rmic to generate the tie. If you do not use the POA, the RMI(IIOP) server
code can be reduced to instantiating the servant (FooImpl foo = new FooImpl())
and binding it to a naming service as is usually done in the RMI(JRMP)
environment. In this case, you need use only the -iiop option to enable rmic to
generate the RMI-IIOP tie. If you omit -iiop, the RMI(JRMP) skeleton is generated.
You must remember also one more important fact when you decide between the
JRMP and IIOP protocols. When you export an RMI-IIOP object on your server,
you do not necessarily have to choose between JRMP and IIOP. If you need a
single server object to support JRMP and IIOP clients, you can export your
RMI-IIOP object to JRMP and to IIOP simultaneously. In RMI-IIOP terminology,
this action is called dual export.
38 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Examples of client–server applications
For CORBA clients, you must also generate IDL from the RMI Java interface by
using the rmic compiler with the -idl option.
All the changes in the import statements for server development apply to client
development. In addition, you must also create a local object reference from the
registered object name. The lookup() method returns a java.lang.Object, and you
must then use the narrow() method of PortableRemoteObject to cast its type. You
generate stubs for IIOP using the rmic compiler with the -iiop option.
40 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Using the ORB
The ORB cleans up only connections that are not busy from the connection cache
table, if the size is of the table is higher than the MinOpenConnections.
v com.ibm.CORBA.NoLocalInterceptors: (default: false)
If this property is set to true, no local PortableInterceptors are driven. This
should improve performance if interceptors are not required when invoking a
co-located object.
v com.ibm.CORBA.ORBCharEncoding: (default: ISO8859_1)
Specifies the ORB’s native encoding set for character data.
v com.ibm.CORBA.ORBWCharDefault: (default: UCS2 )
Indicates that wchar codeset UCS2 is to be used with other ORBs that do not
publish a wchar codeset.
v com.ibm.CORBA.RequestTimeout: (range: 0 through 2147483647) (default:
0=infinity)
Defines the number of seconds to wait before timing out on a Request message.
v com.ibm.CORBA.SendVersionIdentifier: (default: false)
Tells the ORB to send an initial dummy request before it starts to send any real
requests to a remote server. This action determines the partner version of the
remote server ORB from that ORB’s response.
v com.ibm.CORBA.ServerSocketQueueDepth: (range: 50 through 2147483647 )
(default: 0)
The maximum queue length for incoming connection indications (a request to
connect). If a connection indication arrives when the queue is full, the
connection is refused. If the property is not set, the default 0 is used. If the
property is not valid, 50 is used.
v com.ibm.CORBA.ShortExceptionDetails: (default: false)
When a CORBA SystemException reply is created, the ORB, by default, includes
the Java stack trace of the exception in an associated ExceptionDetailMessage
service context. If you set this property to any value, the ORB includes a
toString of the Exception instead.
v com.ibm.tools.rmic.iiop.Debug: (default: false)
The rmic tool automatically creates import statements in the classes that it
generates. If set to true, this property causes rmic to output the mappings of
fully qualified class names to short names.
v com.ibm.tools.rmic.iiop.SkipImports: (default: false)
If this property is set to true, classes are generated with rmic using fully
qualified names only.
Table 3 shows the Sun properties that are now deprecated and the IBM properties
that have replaced them .
Table 3. Deprecated Sun properties
Sun property IBM property
com.sun.CORBA.ORBServerHost com.ibm.CORBA.LocalHost
com.sun.CORBA.ORBServerPort com.ibm.CORBA.ListenerPort
org.omg.CORBA.ORBInitialHost com.ibm.CORBA.BootstrapHost
org.omg.CORBA.ORBInitialPort com.ibm.CORBA.BootstrapPort
org.omg.CORBA.ORBInitialServices com.ibm.CORBA.InitialReferencesURL
42 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Using the ORB
Note that none of these properties are OMG standard properties, despite their
names.
Firstly, this section explains the client side, and describes what the ORB does under
the cover and transparently to the client. Then, the important role of the ORB in
the server-side is explained
Stub creation
In a simple distributed application, the client needs to know (in almost all the
cases) what kind of object it is going to contact and which method of this object it
needs to invoke. Because the ORB is a general framework you must give it general
information about the method that you want to invoke.
For this reason, you implement a Java interface, Foo, which contains the signatures
of the methods that can be invoked in the remote object (see Figure 3).
Stub TIE
rmic-iiop
_Foo_Stub.java _Foo_Tie.java
IIOP
ORB ORB
The client relies on the existence of a server that contains an object that is that Foo
interface. You must, therefore, create a proxy. This proxy is an object, called stub
that acts as an interface between client application and ORB.
To create the stub, run the RMIC compiler on the Java interface: rmic -iiop Foo.
This action generates a file/object that is named _Foo_Stub.
The presence of a stub is not always mandatory for a client application to operate.
When you use particular CORBA features such as the DII (Dynamic Invocation
Interface), you do not require a stub because the proxy code is implemented
directly by the client application. You can also upload a stub from the server to
which you are trying to connect. See the CORBA specification for further details
ORB initialization
In a standalone Java application, the client has to create an instance of the ORB by
calling the static method init(...); for example:
ORB orb = ORB.init(args,props);
For an applet, a similar method is used in which a Java Applet is passed instead of
the string array.
The first step of the ORB initialization is the processing of the ORB properties. The
properties are processed in the following sequence:
1. Check in the applet parameter or application string array
2. Check in the properties parameter (if the parameter exists)
3. Check in the system properties
4. Check in the orb.properties file that is in the <user-home> directory (if the file
exists)
5. Check in the orb.properties file that is in the <java-home>/lib directory (if the
file exists)
6. Fall back on a hardcoded default behavior
The two properties ORBClass and ORBSingletonClass determine which ORB class
has to be instantiated.
The ORB loads its native libraries. Libraries are not mandatory, but they improve
performance.
After this, the ORB starts and initializes the TCP transport layer. If the ListenerPort
property was set, the ORB also opens a ServerSocket that is listening for incoming
requests, as a server-side ORB usually does. At the end of the init() method, the
ORB is fully functional and ready to support the client application.
This reference contains all the information that is necessary to find the remote
object. It also contains some details of the settings of the server to which the object
belongs.
Generally, the client ORB is not supposed to understand the details of the IOR, but
use it as a sort of a key; that is, a reference to the remote object. However, when
client and server are both using an IBM ORB, extra features are coded in the IOR.
44 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
How the ORB works
For example, the IBM ORB adds into the IOR a proprietary field that is called
IBM_PARTNER_VERSION. This field looks like:
49424d0a 00000008 00000000 1400 0005
where:
v The three initial bytes (from left to right) are the ASCII code for IBM, followed
by 0x0A, which specifies that the following bytes handle the partner version.
v The next four bytes encode the length of the remaining data (in this case 8 bytes)
v The next four null bytes are for future use.
v The two bytes for the Partner Version Major field (0x1400) define the release of
the ORB that is being used (1.4.0 in this case).
v The Minor field (0x0005) distinguishes in the same release, service refreshes that
contain changes that have affected the backward compatibility.
Because the IOR is not visible to application-level ORB programmers and the client
ORB does not know where to look for it, another step has to be made. This step is
called the bootstrap process. Basically, the client application needs to tell the ORB
where the remote object reference is located.
Using the NamingContext and the name with which the Remote Object has been
bound in the name service, the client can retrieve a reference to the remote object.
The reference to the remote object that the client holds is always an instance of a
Stub object; that is, your _Foo_Stub.
the client ORB uses GIOP 1.0 to send a request with a simple object key of
AService to port 1050 at host aserver.aworld.aorg. There, the client ORB expects to
find a server for the Aservice that is requested, and returns a reference to itself.
You can then use this reference to look for the remote object.
This naming service is transient. It means that the validity of the contained
references expires when the name service or the server for the remote object is
stopped.
First, the stub code determines whether the implementation of the remote object is
located on the same ORB instance and can be accessed without using the internet.
Note: In this discussion, the remote object will be called FooImpl, which in CORBA
language is referred to as a servant.
If the implementation of the remote object is located on the same ORB instance, the
performance improvement can be significant because a direct call to the object
implementation is done. If no local servant can be found, the stub first asks the
ORB to create a request by invoking its _request() method, specifying the name of
the method to invoke and whether a reply is expected or not.
Note that the CORBA specification imposes an extra indirection layer between the
ORB code and the stub. This layer is commonly known as delegation. CORBA
imposes the layer by using an interface named Delegate. This interface specifies a
portable API for ORB-vendor-specific implementation of the
org.omg.CORBA.Object methods. Each stub contains a delegate object, to which all
org.omg.CORBA.Object method invocations are forwarded. This allows a stub that
is generated by one vendor’s ORB to work with the delegate from another
vendor’s ORB.
When creating a request, the ORB first checks whether the enableLocateRequest
property is set to true. If it is, a LocateRequest is created. The steps of creating this
request are similar to the full Request case.
The ORB gets hold of the IOR of the remote object (the one that was retrieved by a
naming service, for example) and passes the information that is contained in the
IOR (Profile object) to the transport layer.
The transport layer uses the information that is in the IOR (IP address, port
number, object key) to create a connection if it does not already exist. The ORB
TCP/IP transport has an implementation of a table of cached connections for
improving performances, because the creation of a new connection is a
time-consuming process. The connection at this point is not an open
communication channel to the server host. It is only an object that has the potential
to create and deliver a TCP/IP message to a location on the internet. Usually that
involves the creation of a Java socket and a reader thread that is ready to intercept
the server reply. The ORB.connect() is invoked as part of this process.
When the ORB has the connection, it proceeds to create the Request message. In
the message are the header and the body of the request. The CORBA 2.3
specification specifies the exact format. The header contains, for example, local and
remote IP addresses and ports, message size, version of the CORBA stream format
(GIOP 1.x with x=0,1,2), byte sequence convention, request types, and Ids. (See
Chapter 18, “Debugging the ORB,” on page 165 for a detailed description and
example).
46 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
How the ORB works
The body of the request contains several service contexts and the name and
parameters of the method invocation. Parameters are typically serialized.
A service context is some extra information that the ORB includes in the request or
reply, to add several other functions. CORBA defines a few service contexts, such
as the codebase and the codeset service contexts. The first is used for the call-back
feature (see the CORBA specification), the second to specify the encoding of
strings.
In the next step, the stub calls _invoke(). Again it is the delegate invoke() method
that is executed. The ORB in this chain of events calls the send() method on the
connection that will write the request to the socket buffer and flush it away. The
delegate invoke() method waits for a reply to arrive. The reader thread that was
spun during the connection creation gets the reply message, demarshals it, and
returns the correct object.
Servant implementation
The implementations of the remote object can either inherit from
javax.rmi.PortableRemoteObject, or implement a remote interface and use the
exportObject() method to register themselves as a servant object. In both cases, the
servant has to implement the Foo interface. Here, the first case is described. From
now, the servant is called FooImpl.
Tie generation
Again, you must put an interfacing layer between the servant and the ORB code.
In the old RMI(JRMP) naming convention “skeleton” was the name given to the
proxy that was used on the server side between ORB and the object
implementation. In the RMI-IIOP convention, the proxy is called a Tie.
You generate the RMI-IIOP tie class at the same time as the stub, by invoking the
rmic compiler. These classes are generated from the compiled Java programming
language classes that contain remote object implementations; for example, rmic
-iiop FooImpl generates the stub _Foo_Stub.class and the tie _Foo_Tie.class.
Servant binding
The server implementation is required to do the following tasks:
1. Create an ORB instance; that is, ORB.init(...)
2. Create a servant instance; that is, new FooImpl(...)
3. Create a Tie instance from the servant instance; that is, Util.getTie(...)
4. Export the servant by binding it to a naming service
As described for the client side, you must create the ORB instance by invoking the
ORB static method init(...). The usual steps for that method are:
1. Retrieve properties
2. Get the system class loader
3. Load and instantiate the ORB class as specified in the ORBClass property
4. Initialize the ORB as determined by the properties
Then, the server needs to create an instance of the servant class FooImpl.class.
Something more than the creation of an instance of a class happens under the
cover. Remember that the servant FooImpl extends the PortableRemoteObject class,
so the constructor of PortableRemoteObject is executed. This constructor calls the
static method exportObject(...) whose parameter is the same servant instance that
you try to instantiate. The programmer must directly call exportObject() if it is
decided that the servant will not inherit from PortableRemoteObject.
The exportObject() method first tries to load a rmi-iiop tie. The ORB implements a
cache of classes of ties for improving performances. If a tie class is not already
cached, the ORB loads a tie class for the servant. If it cannot find one, it goes up
the inheritance tree, trying to load the parent class ties. It stops if it finds a
PortableRemoteObject class or a java.lang.Object, and returns null. Otherwise, it
returns an instance of that tie that is kept in a hashtable that is paired with the
instance of the tie’s servant. If the ORB cannot get hold of the tie, it guesses that an
RMI (JRMP) skeleton might be present and calls the exportObject method of the
UnicastRemoteObject class. Finally, if all fails, a null tie and exception is thrown.
At this point, the servant is ready to receive remote methods invocations. However,
it is not yet reachable.
In the next step, the server code has to get hold of the tie itself (assuming the ORB
has already done this successfully) to be able to export it to a naming service. To
do that, the server passes the newly-created instance of the servant into the static
method javax.rmi.CORBA.Util.getTie(). This, in turn, fetches the tie that is in the
hashtable that the ORB created. The tie contains the pair of tie-servant classes.
When in possession of the tie, the server must get hold of a reference for the
naming service and bind the tie to it. As in the client side, the server invokes the
ORB method resolve_initial_references(“NameService”). It then creates a
NameComponent, a sort of directory tree object that identifies in the naming
service the path and the name of the remote object reference, and binds together
this NameComponent with the tie. The naming service then makes the IOR for the
servant available to anyone requesting. During this process, the server code sends
a LocateRequest to get hold of the naming server address. It also sends a Request
that requires a rebind operation to the naming server.
Processing a request
During the ORB initialization, a listener thread was created. The listener thread is
listening on a default port (the next available port at the time the thread was
created). You can specify the listener port by using the
com.ibm.CORBA.ListenerPort property. When a request comes in through that
port, the listener thread first creates a connection with the client side. In this case,
it is the TCP transport layer that takes care of the details of the connection. As seen
for the client side, the ORB caches all the connections that it creates.
By using the connection, the listener thread spawns a reader thread to process the
incoming message. When dealing with multiple clients, the server ORB has a
single listener thread and one reader thread for each connection or client.
The reader thread does not fully read the request message, but instead creates an
input stream for the message to be piped into. Then, the reader thread picks up
one of the worker threads in the implemented pool (or creates one if none is
present), and delegates the reading of the message. The worker threads read all the
48 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
How the ORB works
fields in the message and dispatch them to the tie, which unmarshals any
parameters and invokes the remote method.
The service contexts are then created and written to the response output stream
with the return value. The reply is sent back with a similar mechanism, as
described in the client side. After that, the connection is removed from the reader
thread which eventually stops.
Figure 4 shows how the object adapter relates to the ORB, the skeleton, and the
object implementation.
Figure 4. Relationship between the ORB, the object adapter, the skeleton, and the object
implementation
In CORBA 2.1 and below, all ORB vendors had to implement an object adapter,
which was known as the basic object adapter. Because the basic object adapter was
never completely specified with a standard CORBA IDL, vendors implemented it
in many different ways. Therefore, for example, programmers could not write
server implementations that could be truly portable between different ORB
products. A first attempt to define a standard object adapter interface was done in
CORBA 2.1. With CORBA v.2.3, the OMG group released the final corrected
version for a standard interface for the object adapter. This adapter is known as the
portable object adapter (POA).
For more details of the POA, see the CORBA v.2.3 (formal/99-10-07) specification.
The IBM J2SE v.1.4 ORB supports both the POA specification and the proprietary
basic object adapter that is already present in previous IBM ORB versions. As
default, the rmic compiler, when used with the -iiop option, generates RMI-IIOP
ties for servers. These ties are based on the basic object adapter. When a server
implementation uses the POA interface, you must add the -poa option to the rmic
compiler to generate the relevant ties.
If you want to implement an object that is using the POA, the server application
must obtain a POA object. When the server application invokes the ORB method
resolve_initial_reference(RootPOA), the ORB returns the reference to the main POA
object that contains default policies (see the CORBA specification for a complete
list of all the POA policies). You can create new POAs as children of the RootPOA,
and these children can contain different policies. This in turn allows you to
manage different sets of objects separately, and to partition the name space of
objects IDs.
Ultimately, a POA handles Object IDs and active servants. An active servant is a
programming object that exists in memory and has been registered with the POA
by use of one or more associated object identities. The ORB and POA cooperate to
determine on which servant the client-requested operation should be invoked. By
using the POA APIs, you can create a reference for the object, associate an object
ID, and activate the servant for that object. A map of object IDs and active servants
is stored inside the POA. A POA provides also a default servant that is used when
no active servant has been registered. You can register a particular implementation
of this default servant and also of a servant manager, which is an object for
managing the association of an object ID with a particular servant. A simple POA
architecture is represented in Figure 5 on page 51.
50 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
ORB - features
Adapter activator
The POA Manager is an object that encapsulates the processing state of one or
more POAs. You can control and change the state of all POAs by using operations
on the POA manager.
Fragmentation
CORBA specification introduced the concept of fragmentation to handle the
growing complexity and size of marshaled objects in GIOP messages. Graphs of
objects are linearized and serialized inside a GIOP message under the IDL
specification of valuetypes. Fragmentation specifies the way a message can be split
into several smaller messages (fragments ) and sent over the net.
Portable interceptors
CORBA implementations have long had proprietary mechanisms that allow users
to insert their own code into the ORB’s flow of execution. This code, known as
interceptors, is called at particular stages during the processing of requests. It can
directly inspect and even manipulate requests.
Because this message filtering mechanism is extremely flexible and powerful, the
OMG standardized interceptors in the CORBA 2.4.2 specification under the name
“portable interceptors”. The idea is to define a standard interface to register and
execute application-independent code that, among other things, takes care of
passing service contexts. These interfaces are stored in the package
org.omg.PortableInterceptor.* . The implementation classes are in the
com.ibm.rmi.pi.* package of the IBM ORB. All the interceptors implement the
Interceptor interface.
Two classes of interceptors are defined: request interceptors and IOR interceptors.
Request interceptors are called during request mediation. IOR interceptors are
Chapter 5. Understanding the ORB 51
ORB - features
called when new object references are created so that service-specific data can be
added to the newly-created IOR in the form of tagged components.
The ORB calls request interceptors on the client and the server side to manipulate
service context information. Interceptors must register with the ORB for those
interceptor points that are to be executed.
The only interceptor point for IOR interceptors is establish_component. The ORB
calls this interceptor point on all its registered IOR interceptors when it is
assembling the set of components that is to be included in the IOP profiles for a
new object reference. Registration of interceptors is done using the interface
ORBInitializer.
Example:
package pi;
// ClientRequestInterceptor operations
public void send_request(ClientRequestInfo ri)
{ logger(ri, "send_request"); }
52 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
ORB - features
{ logger(ri, "receive_request"); }
// Trivial Logger
public void logger(RequestInfo ri, String point)
{
System.out.println("Request ID:" + ri.request_id() +
" at " name() + "." + point);
}
}
}
First, you must create a class that implements the ORBInitializer class. This class
will be called by the ORB during its initialization:
public class MyInterceptorORBInitializer extends LocalObject implements ORBInitializer {
During the ORB initialization, the ORB runtime gets hold of the ORB properties
that begin with org.omg.PortableInterceptor.ORBInitializerClass;. The remaining
portion is extracted and the corresponding class is instantiated. Then, the pre_init()
and post_init() methods are called on the initializer object.
Corbaloc URIs allow you to specify object references that can be contacted by IIOP,
or found through ORB::resolve_initial_references(). This new format is easier than
IOR is to manipulate. To specify an IIOP object reference, use a URI of the form
(see the CORBA 2.4.2 specification for full syntax):
corbaloc:iiop:<host>:<port>/<object key>
For example, the following corbaloc URI specifies an object with key MyObjectKey
that is in a process that is running on myHost.myOrg.com listening on port 2809.
corbaloc:iiop:myHost.myOrg.com:2809/MyObjectKey
For example:
corbaname::myOrg.com:2050#Personal/schedule
where the portion of the reference up to the hash mark (#) is the URL that returns
the root naming context. The second part is the argument that is used to resolve
the object on the NamingContext.
The INS specified two standard command-line arguments that provide a portable
way of configuring ORB::resolve_initial_references():
v -ORBInitRef takes an argument of the form <ObjectId>=<ObjectURI>. So, for
example, with command-line arguments of:
-ORBInitRef NameService=corbaname::myhost.example.com
54 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
ORB - features
Other features
Among all the other differences with previous versions of IBM ORBs, it is
important to outline the support for GIOP 1.2, an extended and improved RAS
facility.
56 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 6. Understanding the Java Native Interface (JNI)
The specification for the Java Native Interface (JNI) is maintained by Sun
Microsystems Inc. IBM recommends that you read the JNI specification. Go to
http://java.sun.com/ and search the site for JNI. Sun Microsystems Inc maintains
a combined programming guide and specification at http://java.sun.com/docs/
books/jni/.
This chapter gives additional information to help you with JNI operation and
design.
Overview of JNI
The JNI is a set of wrapper functions that enables C or C++ code to access Java
code, and Java code to access C or C++ code. The JNI does very little management;
it mostly provides a vehicle for the code.
Note: In this chapter, C/C++ code is always called native code because it runs
directly on the target platform, unlike Java code, which requires a JVM.
The JNI specification does not have a complete set of rules about how the JNI is to
be implemented. Therefore, different vendors implement JNI in different ways. The
Sun trademark specification and the Java Compatibility Kit (JCK) ensure
compliance to the specification, but not to the implementation. It is a common
mistake to write native JNI code that assumes implementation methods instead of
conforming strictly to the specification. Although this code might not cause any
problems at first, it could cause many problems if it is moved from one vendor’s
JVM to another, or if a vendor changes an implementation strategy.
Three main interactions occur between the Garbage Collector and the JNI. Those
interactions are:
1. Garbage Collector and object references
2. Garbage Collector and global references
3. Garbage Collector and retained garbage
The first two interactions manage Java objects in native code. The third is a result
of the design of the IBM Garbage Collector.
To avoid this problem, the JNI automatically creates a local reference to any object
that is referenced across it. The local reference that it creates for your object is a
pointer to your object. It is created in the stack of the thread that is running your
code. When the Garbage Collector runs, it finds that local reference as part of its
root set of object pointers (see Chapter 2, “Understanding the Garbage Collector,”
on page 7) and therefore does not collect your object.
You can think of local references as invisible automatic variables that are in the
function or method that you use to access a Java object. The invisible variable is
passed on (invisibly) to all the functions that are called within the function that
declares the local reference, and to all the functions that are called by them, and so
on. As with all automatic variables, the local reference goes out of scope when you
exit the function in which it was declared.
Therefore, you have two elements of data for objects to which you refer across the
JNI. You have a real object that exists on the Java heap, and you have a reference to
that object. This reference exists on the stack of your native thread. When the
reference disappears, it does not directly affect the object to which you referred,
but the object might become unreachable and therefore able to be collected by a
future garbage collection cycle. An object can have more than one native reference
to it, and remains uncollectable as long as one or more references exist.
58 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Garbage Collector and object references
env->GetObjectClass (myObject)
}
Here is how the same code would look if you used a local variable to create an
object reference (invisible code is in italics):
static void JNIcode (...)
{
void * myObjectlocalRef;
The myObjectLocalRef is created in the scope of the function or method that creates
the object for which the local reference exists. This imaginary automatic variable
refers to myObject so that it cannot be garbage collected in the scope of the local
reference. The analogy has been expanded a little by the passing of the automatic
variable into all the functions that are called inside the scope. The idea is that the
local reference in JNIcode remains active in the GetObjectClass function, and in
any other functions that it calls. Only when you exit the function (or method) in
which a local reference is created does it become invalid (or out of scope). How
this affects your application is discussed in more detail in “Handling local
references” on page 60.
Another class of references is available. These references are known as weak global
references whose typical function is to cache objects. For more information about
weak global references, see your JNI documentation.
You cannot directly solve this problem; it usually solves itself. Eventually, the
Garbage Collector finds the garbage. Do not assume that you can determine when
garbage should be collected. If this simple answer is enough for you, go to
“Handling local references” on page 60. Otherwise, continue here.
The retained garbage is a result of the conservative nature of the Garbage Collector
reclamation and the use of JNI. You cannot always determine whether a value in
the stack frame is a reference to a Java object, or whether it is a native parameter
value that has been pushed onto the stack.
The Java threads execute as native threads on the native platform. The thread of
execution is defined by the set of frames that is on the native stack. The Garbage
Collector finds part of its set of root objects by scanning the native stack. When a
mixture of native and Java frames exists on the stack, the Garbage Collector might
scan native stack frames and create false root objects. These actions lead to retained
garbage. The JVM attempts to store the limit of the heap when it changes from
Java code to C/C++ code, so that it can control a garbage collection scan.
However, nested or recursive JNI calls (for example, from native code -> Java ->
native code -> Java) cause Java and native frames to become interleaved on the
stack, and the Garbage Collector is forced to scan an area that does not contain
valid heap references. As a result, false root objects are found, and the garbage of
any object graph to which such a root object refers might be kept.
When native code, by way of the JNI, creates or refers to an object that is on the
heap, the JVM can do either of these actions:
v Make a copy of the object in local storage, and return this copy to the caller
v Pin the actual object on the heap, and return a pointer to the caller
The caller is told whether the object is a copy or is pinned, by way of a flag in the
appropriate API call.
The IBM Virtual Machine for Java usually uses a pinning implementation instead
of a copy implementation.
It is very easy to lose a local reference accidentally. That is, the local reference goes
out of scope, but you continue to use the objects to which it used to refer. When
you lose a local reference in this way, the object is not pinned down, and problems
will occur later. The loss of a local reference does not invalidate the object to which
it refers. Your application continues to work normally and to use the object, until a
garbage collection cycle occurs. However, until the space on the heap is moved or
reused, you can continue to use the object. Your code is pointing to invalid space,
but that space continues to hold the valid data that you put into it.
60 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Local reference scope
So your application might seem to work well, but at random intervals, it fails
when an object that you think is valid suddenly disappears. This is the type of
problem that usually occurs late in a product cycle. It can be quite difficult to
isolate. If you always have this type of problem shortly after a garbage collection
cycle with compaction, when objects are moved, it is a good hint that local
references are being misused.
void myJNIfunc2 ()
{
jobject obj;
obj = myJNIfunc1 ()
..
..
}
The reason for this is that the references to objects in the C code are not references
that the Garbage Collector normally follows. They are C or C++ type references
that are generated by the native compiler and are, therefore, not truly pointers into
the Java heap, which are what the Garbage Collector uses to find its root set of
objects. The native reference to a Java object is translated appropriately in a JNI
function. So, to make it work, the JVM creates a special stack frame when a JNI
function is entered, and reserves a set number of locations in the frame for any
pointers (local references) that the function might need. When the Garbage
Collector looks for root objects, it always looks at this area of the stack frame.
Figure 6. Thread stack pointing to an object so that the Garbage Collector can see the object
myJNIFunc1
stack frame
popped Object
obj
myJNIFunc2
stack frame
Object
Figure 7. Thread stack not pointing to an object so that the Garbage Collector cannot see the object
The use of obj now can be fatal because a garbage collection cycle can overwrite
the data to which obj refers. Clearly, a local reference operates like an automatic
reference. You cannot rely on it outside the function in which the local reference
was generated.
Another incorrect way to refer to an object outside the scope of its local reference
is:
static jclass cls = 0;
void myJNIfunc
{
62 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Local reference scope
...
if (cls == 0)
{
cls = (*env)->GetObjectClass(env, obj);
if (cls == 0)
{
... /* error */
}
}
// there’s no local ref to cls at this point
...
}
The error occurs because any local reference to cls goes out of scope on the first
exit from myJNIfunc. Therefore, the object could be garbage collected although the
static variable, which the Garbage Collector cannot examine, still contains the
reference. Again, no area in the stack directly refers to cls.
This message does not indicate an error. It is warning from the JVM that your
application has more local references than can be contained in the storage that you
first allocated for them. The local reference storage was described in the previous
section (see Figure 6 on page 62). The message suggests that you might want to
check your JNI code to see why you have many outstanding local references, and
decide whether it would be better if you managed them yourself (see “Manually
handling local references”). Normally, it is assumed that a function or method will
not hold many references at the same time. If, however, you have designed you
code to hold many references, you can ignore the message.
The JVM does not stop storing local references when this message appears; it
extends the storage capacity, as necessary. The execution of your application is not
affected in any way by this message, except for a small processing overhead. If
your application is designed this way and the message becomes annoying, or if
you are not willing to accept the overhead of recreating stack frames, JNI calls are
available that enable you to increase the capacity of the local reference storage.
The JNI specification does not set the local reference capacity of a JVM, nor does it,
require (or deny) use of this message. Therefore, this message might or might
appear. If it does, it might appear at different times for different JVMs.
Ensure that you do not refer to an object after you delete its local reference unless
you have a global reference to it. It might be good housekeeping to throw away a
local reference to an object when you have attached a global reference to it.
Handling exceptions
Exceptions give you a way to handle errors in your application. Java has a clear
and consistent strategy for the handling of exceptions, but C/C++ code does not.
Therefore, the Java JNI does not throw an exception when it detects a fault because
it does not know how, or even if, the native code of an application can handle it.
64 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Using the isCopy flag
The isCopy flag is an output parameter. You cannot set it, on entry to a JNI
function, to specify whether you want copy or pin. You do not have to use this
flag at all. You can pass NULL into the JNI function to indicate that you do not
care what the result is.
If the flag indicates a copy, a copy of the data has been taken. If the flag indicates
pinning, the data that is on the heap has been marked as referenced and pinned.
Pinned data cannot be moved in a compaction cycle, nor collected. If the data is
pinned, you effectively have a direct pointer to the data that is on the Java heap.
Clearly, you must free the space that is used for a copy of the data. Also, you must
free the data when it is pinned. By doing this, you tell the JVM that it can unpin
the data again. For example, the GetBooleanArrayElements call must always be
followed by a ReleaseBooleanArrayElements call, whatever the setting of the
isCopy flag.
The IBM Virtual Machine for Java generally uses the pin implementation. A
common mistake is to think that only copied data needs to be freed. If you assume
that you need free only data that is copied, the heap gradually becomes more and
more fragmented with bits of uncollectable, pinned data. Eventually, a failure
occurs.
Use of the isCopy flag is one of the JNI specification details in which you might
accidentally code to a JVM that prefers the copy method. Everything works
correctly if you accidentally free only copied data. If you swap to a pinning JVM
(or the JVM that you use changes its algorithm), code that was working fails if it is
not written to specification.
The JNI specification also states: “It is not possible to predict whether any given
JVM will copy or pin data on any particular JNI call”. If the flag indicates that a
copy has been used, another trap opens in which you must be sensitive to the
mode flag in the corresponding release call (see “Using the mode flag”).
Always call the Release<something> function after a function that is using the
isCopy flag.
You must use this flag correctly with respect to the setting of the corresponding
isCopy flag. You need to know what the isCopy flag is telling you (see “Using the
isCopy flag”). If the isCopy flag indicates that the returned data is pinned, any
preceding changes that you made to the data have been copied directly into the
Java heap, and the mode parameter is ignored.
If, however, the isCopy flag indicates that the returned data is a copy, you must
use the mode flag to ensure that all changes that you made are actually actioned.
If you do not change the array data that you got as a copy, use JNI_ABORT
because it prevents unnecessary copying. If you do change the data, use 0 or
JNI_COMMIT to ensure that your changes actually happen, or use JNI_ABORT if
appropriate.
v If the isCopy flag indicates that the data is pinned, use the JNI_ABORT setting.
v If the isCopy flag indicates that the data is a copy, use the appropriate setting.
A complicated use of these flags is necessary only if you want to do some special
optimization. This generic way does not release you from the need to think about
synchronization (see “Synchronization”).
Synchronization
When you get array elements through a Get<something>ArrayElements call, you
must think about synchronization. Whether or not the data is pinned, two entities
are involved in accessing the data:
v The Java code in which the data entity is declared and used
v The native code that accesses the data through the JNI
It is likely that these two entities are separate threads, in which case contention
occurs.
66 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Synchronization
In this particular scenario, note that the code would work with a pinning JVM.
Because each thread writes only its own bit of the data and the mode flag is
ignored, no contention occurs. This is another example of how code that is not
strictly to specification would work with one JVM implementation and not with
another. Although this scenario involves an array elements copy, you can see that
pinned data can also be corrupted when two threads access it at the same time.
Take care if the getter method says the data is pinned.
Be very careful about how you synchronize access to array elements. The JNI
interfaces allow you to access regions of Java entities to reduce problems in this
sort of interaction. In the above scenario, the thread that is writing the data should
write into its own region, and the thread that is reading the data should read only
its own region. This works whatever the JNI implementation is.
If you think that you have a problem with the interaction between user-written
native code and the JVM (that is, a JNI problem), you can run diagnostics that help
you check the JNI transitions. to invoke these diagnostics, specify the -Xcheck:jni
option when you start up the JVM.
The -Xcheck:jni option activates a set of wrapper functions around the JNI
functions. The wrapper functions perform checks on the incoming parameters such
as:
v Whether the call and the call that initialized JNI are on the same thread.
v Whether the object parameters are valid objects.
v Whether local or global references refer to valid objects.
v The type matching, in get or set field operations.
v The validity of static and nonstatic field IDs.
v Whether strings are valid and non-null.
v Whether array elements are non-null.
v The types on array elements.
Output from jnichk appears on the standard output stream, and looks like:
JNI warning in FindClass: argument #2 is a malformed identifier ("invalid.name")
Warning occurred in com/ibm/examples/JNIExample.nativeMethod() [Ljava/lang/String];
Note: On some platforms, reusing a va_list in a second JNI call (for example,
when calling CallStaticVoidMethodV() twice with the same arguments)
causes the va_list to be corrupted and the second call to fail. To ensure that
the va_list is not corrupted, use the standard C macro va_copy() in the first
call. By default, -Xcheck:jni ensures that va_lists are not being reused. Use
the novalist suboption to disable this check only if your platform allows
reusing va_list without va_copy.
JNI checklist
Table 4. JNI checklist
Remember Outcome of nonadherence
Check your code to ensure that you do not Random crashes (depending on what you
accidentally lose local references. If in doubt, pick up in the overwritten object space)
create a global reference and ensure that you happen at random intervals.
delete that global reference when
appropriate.
Local references cannot be saved in global As above.
variables.
68 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JNI checklist
70 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 7. Understanding Java Remote Method Invocation
Java Remote Method Invocation (Java RMI) enables you to create distributed Java
technology-based applications that can communicate with other such applications,
in which the methods of remote Java objects can be invoked from other Java
virtual machines, possibly on different hosts. RMI uses object serialization to
marshal and unmarshal parameters and does not truncate types, supporting true
object-oriented polymorphism.
e. If the server object throws an exception, the server catches it and marshals it
down the wire instead of the return value.
4. Back on the client side:
a. The return value of the RMI is unmarshalled and returned from the stub
back to the client code itself.
b. If an exception is thrown from the server, that is unmarshalled and thrown
from the stub.
With the connectionPool enabled, threads are created only if there is no thread in
the pool that can be reused. In the current implementation of the connection Pool,
the RMI connectionHandler threads are added to a pool and are never removed.
Because you cannot currently fine tune the number of threads in the pool, enabling
thread pooling is not recommended for applications that have only limited RMI
usage. Such applications have to live with these threads during the RMI off-peak
times as well. Applications that are mostly RMI intensive can benefit by enabling
the thread pooling because the connection handlers will be reused and there is no
overhead if these threads are created for every RMI call.
The DGC abstraction is used for the server side of Distributed Garbage Collection.
This interface contains two methods: dirty() and clean(). A dirty() call is made
when a remote reference is unmarshalled in a client (the client is indicated by its
VMID). A corresponding clean() call is made when no more references to the
remote reference exist in the client. A failed dirty() call must schedule a strong
clean() call so that the call’s sequence number can be retained in order to detect
future calls received out of order by the distributed garbage collector.
A reference to a remote object is leased for a period of time by the client holding
the reference. The lease period starts when the dirty call is received. The client has
to renew the leases, by making additional dirty calls, on the remote references it
holds before such leases expire. If the client does not renew the lease before it
expires, the distributed garbage collector assumes that the remote object is no
longer referenced by that client.
DGCClient implements the client side of the RMI Distributed Garbage Collection
system. The external interface to DGCClient is the registerRefs() method. When a
LiveRef to a remote object enters the JVM, it must be registered with the
DGCClient to participate in distributed garbage collection. When the first LiveRef
to a particular remote object is registered, a dirty call is made to the server-side
distributed garbage collector for the remote object, which returns a lease
72 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Understanding Distributed Garbage Collection (DGC)
guaranteeing that the server-side DGC will not collect the remote object for a
certain period of time. While LiveRef instances to remote objects on a particular
server exist, the DGCClient periodically sends more dirty calls to renew its lease.
The DGCClient tracks the local availability of registered LiveRef instances using
phantom references. When the LiveRef instance for a particular remote object is
garbage collected locally, a clean() call is made to the server-side distributed
garbage collector, indicating that the server no longer needs to keep the remote
object alive for this client. The RenewCleanThread handles the asynchronous
client-side DGC activity by renewing the leases and making clean calls. So this
thread would wait until the next lease renewal or until any phantom reference is
queued for generating clean requests as necessary.
http://java.sun.com/j2se/1.4.2/docs/guide/rmi/spec/rmi-exceptions.html#3601
Properties settings that are useful for tuning, logging, or tracing RMI servers and
clients can be found at:
http://java.sun.com/j2se/1.4.2/docs/guide/rmi/javarmiproperties.html
http://java.sun.com/j2se/1.4.2/docs/guide/rmi/faq.html
Network monitoring tools like netstat and tcpdump are useful for debugging RMI
problems at the network level.
No traditional level 1, level 2, and level 3 service exists for Java. However, the Java
Technology Centre (JTC) maintains a Java L3 service team. Initially, your problem
report will probably go to the L2 service team for the product that you are using.
They will forward to the JTC if necessary. You can also send problem reports direct
to the JTC, as described in this part of the book.
See Part 3, “Problem determination,” on page 89 for specific information for your
platform.
Data to include
The following checklist describes the information that you could include in your
problem report:
v Version information (-version from the command-line).
v Command-line options.
v Environment, non-default settings.
v OS and OS version.
v OS distribution (if applicable).
v Javadump.
v For crashes or hangs you should send a full system dump. These have the form
core.<date>.<time>.<pid>.dmp. For other situations, send a raw heap dump –
this is usually named heapdump.<date>.<time>.<pid>.dmp. (See Chapter 12,
“First steps in problem determination,” on page 91 for instructions on how to
enable these dumps.)
Note: For diagnosing suspected Java heap problems or Java memory leaks, the
raw heap dump files are more useful to IBM service than the system
dump files.
v XML file generated from the raw heap or a system dump, which is usually
named <original dump name>.xml. This file is used by the jdmpview tool for
dump analysis (see Chapter 15, “Linux problem determination,” or Chapter 16,
“Windows problem determination,” as appropriate, for instructions about how
to use the jextract command to create the xml file from the core dump).
v CEEDUMP and transactional dumps for z/OS; see Chapter 17, “z/OS problem
determination.”
v Verbose output, where required.
v Data from any diagnostics that you run.
v Data from JIT diagnostics.
v Platform-specific data.
For information on how to gather this data, see Part 3, “Problem determination,”
on page 89.
Things to try
Refer to Chapter 12, “First steps in problem determination,” on page 91.
Test cases
It is easier for IBM Service to solve a problem when a test case is available. Include
a test case with your problem report wherever possible.
If your application is too large or too complex to reduce into a test case, provide, if
possible, some sort of remote login so that IBM can see the problem in your
environment. (For example, install a VNC/Remote Desktop server and provide
logon details in the problem report.) This option is not very effective because IBM
has no control over the target JVM.
If no test case is available, analysis takes longer. IBM might send you
specially-instrumented JVMs that require the collection of the diagnostics data
while you are using them. This method often results in a series of interim fixes,
each providing progressively more instrumentation in the fault area. This operation
obviously increases the turnaround time of the problem. It might be quicker for
you to invest time and effort into a test case instead of having a costly cycle of
installing repeated JVM instrumentation onto your application.
80 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Performance problems – questions
Always obtain and give as much detail as possible before you attempt to collect or
analyze data. Ask the following questions about the performance problem:
v Can the problem be demonstrated by running a specific test case or a sequence
of events?
v Is the slow performance intermittent?
v Does it become slow, then disappear for a while?
v Does it occur at particular times of the day or in relation to some specific
activity?
v Are all, or only some, operations slow?
v Which operation is slow? For example, elapsed time to complete a transaction,
or time to paint the screen?
v When did the problem start occurring?
v Has the condition existed from the time the system was first installed or went
into production?
v Did anything change on the system before the problem occurred (such as adding
more users or upgrading the software installed on the system)?
v If you have a client and server operation, can the problem be demonstrated
when run only locally on the server (network versus server problem)?
v Which vendor applications are running on the system, and are those
applications included in the performance problem? For example, the IBM
WebSphere Application Server?
v What effect does the performance problem have on the users?
v Which part of your analysis made you decide that the problem is caused by a
defect in the SDK?
v What hardware are you using? Which models; how many CPUs; what are the
memory sizes on the affected systems; what is the software configuration in
which the problem is occurring?
v Does the problem affect only a single system, or does it affect multiple systems?
v What are the characteristics of the Java application that has the problem?
v Which performance objectives are not being met?
v Did the objectives come from measurements on another system? If so, what was
the configuration of that system?
Two more ways in which you can help to get the problem solved more quickly are:
v Provide a clear written statement of a simple specific example of the problem,
but be sure to separate the symptoms and facts from the theories, ideas, and
your own conclusions. PMRs that report “the system is slow” require extensive
investigation to determine what you mean by slow, how it is measured, and
what is acceptable performance.
v Provide information about everything that has changed on the system in the
weeks before the problem first occurred. By missing something that changed,
you can block a possible investigation path and delay the solution of the
problem. If all the facts are available, the team can quickly reject those that are
not related.
82 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 10. Advice about problem submission
This chapter describes how to submit a problem report, and explains the
information that you should include in that report:
v “Raising a problem report”
v “What goes into a problem report?”
v “Problem severity ratings”
v “Escalating problem severity” on page 84
An artificial increase of the severity of your problem does not result in quicker
fixes. IBM queries your assessed severity if it seems too high. Problems that are
assessed at Sev 1 require maximum effort from the IBM Service team and,
therefore, 24-hour customer contact to enable Service Engineers to get more
information.
For problems at Sev 1, you can escalate the severity higher into a ’critsit’. This
route is available only to customers who have service contracts and to internal
customers.
84 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 11. Submitting data with a problem report
Having followed the advice that is given in the previous two chapters, you
probably have a large amount of data to send to IBM in one or more files. This
chapter describes how to transmit data to IBM Java service. Data can be sent to
IBM in three ways:
v Java service maintain an anonymous ftp server, named ’javaserv’, for sending or
receiving data, This server is behind the IBM firewall and is therefore accessible
only inside IBM. Ask your SE to transmit the data.
v IBM also maintains an anonymous ftp public server. Java service prefer the use
of the javaserv ftp because the IBM server is not under the control of the IBM
Java Technology Center.
v You can also use an ftp server of your own if you want to. In your PMR, include
details of how to log on, and where the data is. Java service might need to send
data to you; for example an interim fix (see “When you will receive your fix” on
page 87). IBM uses the same server to send (PUT) data as Java service did to
receive (GET) it. If you use your own server, provide an address that Java
service can use to write to your server.
Files are kept on the server for only a short time, so notify IBM support
immediately after you have sent the files.
86 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
submitting data with a problem report
IBM periodically produces service refreshes of Java. After you have been notified
that your problem has been solved, you must obtain the next service refresh.
Service refreshes are fully supported by IBM. The version number in your JVM
(see Part 3, “Problem determination,” on page 89) identifies the service refresh level
that you are using. In some cases (for example when you urgently need a fix for a
Sev 1 problem), IBM service provides you with an overnight build as an electronic
fix (interim fix). An interim fix is a set of the Java binaries that contains a fix for
your problem. IBM support sends you this set of binaries to replace your original
binaries. Interim fixes are ftp’d to you through the same server that you used to
send in your problem data. Interim fixes are used to validate that a fix is good in
your environment, or to allow you to continue work on your project while waiting
for the next service refresh. Interim fixes are not supported by Java service,
because they have not been officially certified as Java-compatible. If you receive an
interim fix, you must get the next service refresh immediately it becomes available.
To use this part, go to the chapter that relates to your platform. If your application
runs on more than one platform and is exhibiting the same problem on them all,
go to the chapter about the platform to which you have the easiest access.
If you use the IBM WebSphere Application Server, the above guidance applies to
you, but read Chapter 13, “Working in a WebSphere Application Server
environment,” on page 93 first, because the platform-specific chapters discuss
subjects such as environment variables, and you will need the additional
information that is given in the chapter for the WebSphere Application Server.
A couple of JVM issues do not fit neatly into the platform model, and these have
their own chapters:
v Chapter 18, “Debugging the ORB,” on page 165
v Chapter 19, “NLS problem determination,” on page 179
If you have problems in these areas, check out the appropriate chapter in addition
to general diagnostics about your platform.
92 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 13. Working in a WebSphere Application Server
environment
The WebSphere Application Server depends on the JVM and ORB technology.
Refer to Appendix A, “Compatibility tables,” on page 313 for WebSphere
Application Server/JVM/ORB compatibility tables.
Note that the 64-bit JVM can work on a 32-bit kernel if the hardware is 64-bit. In
that case, you have to enable a 64-bit application environment using smitty:System
Environments -> Enable 64-bit Application Environment.
Occasionally the configuration process does not work correctly, or the environment
might be altered, affecting the operation of the JVM. In these conditions, you can
make checks to ensure that the JVM’s required settings are in place:
1. Check that the SDK and JRE files have been installed in the correct location and
that the correct permissions are set. See the User Guide for more information on
expected files and their location. Test the java and javac commands to ensure
they are executable.
The default installation directory is in /usr/java142_64. For developer kits
packaged with other products, the installation directory might be different;
consult your product documentation.
2. Ensure that the PATH environment variable points to the correct Java
executable (using which java), or that the application you are using is pointing
to the correct Java directory. You must include /usr/java142_64/jre/bin:/usr/
java142_64/bin in your PATH environment variable . If it is not present, add it
by using export PATH=/usr/java142_64/jre/bin:/usr/java142_64/bin:$PATH.
3. Ensure that the LANG environment variable is set to a supported locale. You
can find the language environment in use using echo $LANG, which should
report one of the supported locales as documented in the User Guide shipped
with the SDK.
4. Ensure that all the prerequisite AIX maintenance and APARs have been
installed. The prerequisite APARs and filesets will have been checked during an
install using smitty or installp. You can find the list of prerequisites in the
User Guide that is shipped with the SDK. Use lslpp -l to find the list of
current filesets. Use instfix -i -k <apar number> to test for the presence of an
APAR and instfix -i | grep _ML to find the installed maintenance level.
The ReportEnv tool, available from the Java service team, plugs into your JVM and
reports on the JVM environment in real time. Your JVM environment affects the
| These values are the ″soft″ limit, and are applied for each user. These
| values cannot exceed the ″hard″ limit value. To display and change the
| ″hard″ limits, you can run the same ulimit commands using the
| additional -H flag.
| The ulimit -c value for the soft limit is ignored and the hard limit
| value is used so that the core file is generated. You can disable the
| generation of core files by using this Java command-line option:
| -Xdump:system:none
| 2. Set the following in smitty:
| a. Start smitty as root
| b. Go to System Environments -> Change/Show Characteristics of
| Operating System
| c. Set the Enable full CORE dump option to TRUE
| Alternatively, you can run chdev -l sys0 -a fullcore=’true’ as root.
| You can check the setting with lsattr -D -c sys -a fullcore -H,
| which should produce output similar to this:
| attribute deflt description user_settable
| fullcore false Enable full CORE dump True
| Java Virtual Machine settings
| The JVM settings should be in place by default, but you can check these
| settings using the following instructions.
| To check that the JVM is set to produce a core file when a failure occurs,
| run the following:
| java -Xdump:what
96 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - setting up and checking your environment
| -Xdump:system:
| events=gpf+abort,
| label=/u/cbailey/core.%Y%m%d.%H%M%S.%pid.dmp,
| range=1..0,
| priority=999,
| request=serial
| You can change and set options using the command-line option -Xdump,
| which is described in Chapter 24, “Using dump agents,” on page 213.
| Available disk space
| You must ensure that the disk space available is sufficient for the core file
| to be written to it. The core file is written to the directory specified in the
| label option. Up to 2 GB of free space might be required for 32-bit and
| over 6 GB for 64-bit system dumps. The Java process must have the correct
| permissions to write to that location.
bootinfo –K
This command shows if the 64–bit kernel is active.
bootinfo –y
This command shows whether the hardware in use is 32-bit or 64-bit.
dbx
The AIX debugger. Examples of use can be found throughout this chapter.
The Java 142 SDK also includes a dbx Plug-in for additional help debugging Java
applications. See “DBX Plug-in” on page 106 for more information.
iostat
Use this command to determine if a system has an I/O bottleneck. The read and
write rate to all disks is reported. This tool is useful in determining if you need to
’spread out’ the disk workload across multiple disks. iostat also reports the same
CPU activity that vmstat does.
lsattr
This command details characteristics and values for devices in the system. To
obtain the type and speed of processor 0, use:
# lsattr -El proc0
state enable Processor state False
type PowerPC_POWER3 Processor type False
frequency 200000000 Processor Speed False
Processor 0 may not be available to you if you are using an LPAR. Use
bindprocessor -q to list the available processors.
lsconf
This command shows basic hardware and configuration details. For example:
System Model: IBM,7040-681
Machine Serial Number: 835A7AA
Processor Type: PowerPC_POWER4
Number Of Processors: 8
Processor Clock Speed: 1100 MHz
CPU Type: 64-bit
Kernel Type: 64-bit
LPAR Info: 5 JAVADEV1 - kukicha
Memory Size: 10240 MB
Good Memory Size: 10240 MB
Platform Firmware level: 3H041021
Firmware Version: IBM,RG041021_d78e05_s
Console Login: enable
Auto Restart: true
Full Core: true
Network Information
Host Name: bb1p5-1.hursley.ibm.com
IP Address: 9.20.136.92
Sub Netmask: 255.255.255.128
Gateway: 9.20.136.1
Name Server: 9.20.136.11
Domain Name: hursley.ibm.com
98 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - general debugging techniques
netpmon
This command uses the trace facility to obtain a detailed picture of network
activity during a time interval. It also displays process CPU statistics that show:
v The total amount of CPU time used by this process,
v The CPU usage for the process as a percentage of total time
v The total time that this process spent executing network-related code.
For example,
netpmon -o /tmp/netpmon.log; sleep 20; trcstop
is used to look for a number of things such as CPU usage by program, first level
interrupt handler, network device driver statistics, and network statistics by
program. Add the -t flag to produce thread level reports. The following output
shows the processor view from netpmon.
Process CPU Usage Statistics:
-----------------------------
Network
Process (top 20) PID CPU Time CPU % CPU %
----------------------------------------------------------
java 12192 2.0277 5.061 1.370
UNKNOWN 13758 0.8588 2.144 0.000
gil 1806 0.0699 0.174 0.174
UNKNOWN 18136 0.0635 0.159 0.000
dtgreet 3678 0.0376 0.094 0.000
swapper 0 0.0138 0.034 0.000
trcstop 18460 0.0121 0.030 0.000
sleep 18458 0.0061 0.015 0.000
You can also request that less information is gathered. For example to look at
socket level traffic use the ″-O so″ option:
netpmon -O so -o /tmp/netpmon_so.txt; sleep 20; trcstop
netstat
Use this command with the –m option to look at mbuf memory usage, which will
tell you something about socket and network memory usage. By default, the
extended netstat statistics are turned off in /etc/tc.net with the line:
/usr/sbin/no -o extendednetstats=0 >>/dev/null 2>&1
To turn on these statistics, change to extendednetstats=1 and reboot. You can also
try to set this directly with no. When using netstat -m, pipe to page because the
first information is some of the most important:
67 mbufs in use:
64 mbuf cluster pages in use
272 Kbytes allocated to mbufs
0 requests for mbufs denied
0 calls to protocol drain routines
0 sockets not created because sockthresh was reached
100 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - general debugging techniques
nmon
Nmon is a free interactive software tool that gives much of the same information
as topas, but saves the information to a file in Lotus 123 and Excel formats. The
download site is www.ibm.com/servers/esdd/articles/analyze_aix/. The
information that is collected includes CPU, disk, network, adapter statistics, kernel
counters, memory, and the ’top’ process information.
no
Use the no command to configure network attributes. The no command sets or
displays current network attributes in the kernel.
The wall is the maximum amount of memory assigned to the network memory
buffer.
ps
The Process Status (ps) is used to monitor:
v A process.
v Whether the process is still consuming CPU cycles.
v Which threads of a process are still running.
Where
UID
The user ID of the process owner. The login name is printed under the -f flag.
PPID
The Parent Process ID.
PID
The Process ID.
C CPU utilization, incremented each time the system clock ticks and the process
is found to be running. The value is decayed by the scheduler by dividing it
by 2 every second. For the sched_other policy, CPU utilization is used in
determining process scheduling priority. Large values indicate a CPU intensive
process and result in lower process priority whereas small values indicate an
I/O intensive process and result in a more favorable priority.
STIME
The start time of the process, given in hours, minutes, and seconds. The start
time of a process begun more than twenty-four hours before the ps inquiry is
executed is given in months and days.
TTY
The controlling workstation for the process.
TIME
The total execution time for the process.
CMD
The full command name and its parameters.
Where
USER
The user name of the person running the process.
TID
The Kernel Thread ID of each thread.
ST
The state of the thread:
O Nonexistent.
R Running.
S Sleeping.
W Swapped.
Z Canceled.
T Stopped.
CP
CPU utilization of the thread.
PRI
Priority of the thread.
SC
Suspend count.
ARCHON
Wait channel.
102 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - general debugging techniques
F Flags.
TAT
Controlling terminal.
BAND
CPU to which thread is bound.
sar
Use the sar command to check the balance of CPU usage across multiple CPU’s. In
this example below, two samples are taken every five seconds on a 2-processor
system that is 80% utilized.
# sar -u -P ALL 5 2
Average 0 32 47 0 20
1 34 45 0 22
- 33 46 0 21
svmon
This command captures snapshots of virtual memory. Using svmon to take
snapshots of the memory usage of a process over regular intervals allows you to
monitor memory usage. The following usage of svmon generates regular snapshots
of a process memory usage and writes the output to a file:
svmon -P [process id] -m -r -i [interval] > output.file
in which:
Vsid
Segment ID
Esid
Segment ID: corresponds to virtual memory segment. The Esid maps to the
Virtual Memory Manager segments. By understanding the memory model that
is being used by the JVM, you can use these values to determine whether you
are allocating or committing memory on the native or Java heap.
Type
Identifies the type of the segment:
pers Indicates a persistent segment.
work Indicates a working segment.
clnt Indicates a client segment.
mmap Indicates a mapped segment. This is memory allocated using mmap in
a large memory model program.
Description
If the segment is a persistent segment, the device name and i-node number of
the associated file are displayed.
If the segment is a persistent segment and is associated with a log, the string
log is displayed.
If the segment is a working segment, the svmon command attempts to
determine the role of the segment:
kernel
The segment is used by the kernel.
shared library
The segment is used for shared library text or data.
process private
Private data for the process.
shmat/mmap
Shared memory segments that are being used for process private data,
because you are using a large memory model program.
Inuse
The number of pages in real memory from this segment.
Pin
The number of pages pinned from this segment.
Pgsp
The number of pages used on paging space by this segment. This value is
relevant only for working segments.
104 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - general debugging techniques
Addr Range
The range of pages that have been allocated in this segment. Addr Range
displays the range of pages that have been allocated in each segment, whereas
Inuse displays the number of pages that have been committed. For instance,
Addr Range might detail more pages than Inuse because pages have been
allocated that are not yet in use.
tprof
The tprof command reports CPU usage for individual programs and the system as
a whole. This command is a useful tool for anyone with a Java program that might
be CPU-bound and who wants to know which sections of the program are most
heavily using the CPU.
The tprof command can charge CPU time to object files, processes, threads,
subroutines (user mode, kernel mode and shared library) and even to source lines
of programs or individual instructions. Charging CPU time to subroutines is called
profiling and charging CPU time to source program lines is called micro-profiling.
topas
Topas is a useful graphical interface that will give you immediate information
about system activity. The screen looks like this:
Topas Monitor for host: aix4prt EVENTS/QUEUES FILE/TTY
Mon Apr 16 16:16:50 2001 Interval: 2 Cswitch 5984 Readch 4864
Syscall 15776 Writech 34280
Kernel 63.1 |################## | Reads 8 Rawin 0
User 36.8 |########## | Writes 2469 Ttyout 0
Wait 0.0 | | Forks 0 Igets 0
Idle 0.0 | | Execs 0 Namei 4
Runqueue 11.5 Dirblk 0
Network KBPS I-Pack O-Pack KB-In KB-Out Waitqueue 0.0
lo0 213.9 2154.2 2153.7 107.0 106.9
tr0 34.7 16.9 34.4 0.9 33.8 PAGING MEMORY
Faults 3862 Real,MB 1023
Disk Busy% KBPS TPS KB-Read KB-Writ Steals 1580 % Comp 27.0
hdisk0 0.0 0.0 0.0 0.0 0.0 PgspIn 0 % Noncomp 73.9
PgspOut 0 % Client 0.5
Name PID CPU% PgSp Owner PageIn 0
java 16684 83.6 35.1 root PageOut 0 PAGING SPACE
java 12192 12.7 86.2 root Sios 0 Size,MB 512
lrud 1032 2.7 0.0 root % Used 1.2
aixterm 19502 0.5 0.7 root NFS (calls/sec) % Free 98.7
topas 6908 0.5 0.8 root ServerV2 0
ksh 18148 0.0 0.7 root ClientV2 0 Press:
gil 1806 0.0 0.0 root ServerV3 0 "h" for help
trace
This command captures a sequential flow of time-stamped system events. The
trace is a valuable tool for observing system and application execution. While
many of the other tools provide high level statistics such as CPU and I/O
utilization, the trace facility helps expand the information about where the events
happened, which process is responsible, when the events took place, and how they
are affecting the system. The curt postprocessing tool can extract information from
the trace. It provides statistics on CPU utilization and process and thread activity.
Another postprocessing tool is splat, the Simple Performance Lock Analysis Tool.
This tool is used to analyze lock activity in the AIX kernel and kernel extensions
for simple locks.
truss
This command traces a process’s system calls, dynamically loaded user-level
function calls, received signals, and incurred machine faults.
vmstat
Use this command to give multiple statistics on the system. The vmstat command
reports statistics about kernel threads in the run and wait queue, memory paging,
interrupts, system calls, context switches, and CPU activity. The CPU activity is
percentage breakdown of user mode, system mode, idle time, and waits for disk
I/O.
| DBX Plug-in
| The Plug-in for the AIX DBX debugger gives DBX users enhanced features when
| working on Java processes or core files generated by Java processes.
| The Plug-in requires a version of DBX that supports the Plug-in interface. Use the
| DBX command pluginload to find out whether your version of DBX has this
| support. All supported AIX versions include this support.
| The commands available after loading the Plug-in can be listed by running:
| plugin java help
106 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - general debugging techniques
| You can also use DBX to debug your native JNI code by specifying the full path to
| the java program as follows:
| dbx /usr/java142_64/jre/bin/java
| Before you start working with DBX, you must set the $java variable. Start DBX and
| use the dbx set subcommand. Setting this variable causes DBX to ignore the
| non-breakpoint traps generated by the JIT. You can also use a pre-edited command
| file by launching DBX with the -c option to specify the command file:
| dbx -c .dbxinit
| Although the DBX Plug-in is supplied as part of the SDK, it is not supported.
| However, IBM will accept bug reports.
Diagnosing crashes
A crash can occur because of a fault in the JVM or because of a fault in native
(JNI) code being run in the Java process. Therefore, if the application does not
include any JNI code and does not use any third-party packages that have JNI
code (for example, JDBC application drivers), the fault must be in the JVM, and
should be reported to IBM Support through the normal process.
If a crash occurs, you should gather some basic documents. These documents
either point to the problem that is in the application or third party package JNI
code, or help the IBM JVM Support team to diagnose the fault.
Documents to gather
When a crash takes place, the following diagnostic data is required to help
diagnose the problem:
| v The output of stackit.sh run against the core file located as specified by the
| label field of -Xdump:what. stackit.sh is a script that runs a dbx session and is
| available from your Support Representative or from [email protected].
| v The output of Jjextract run against the core file:
| jextract [core file]
v stderr/stdout files
You can check for the first cause by using the dbx command thread info and
looking at the stack pointer, stack limit, and stack base values for the current
thread. If the value of the stack pointer is close to that of the stack base, you might
have had a stack overflow. A stack overflow occurs because the stack on AIX
grows from the stack limit downwards towards the stack base. If the problem is a
native stack overflow, you can solve the overflow by increasing the size of the
native stack from the default size of 400K using the command-line option
-Xss<size>. You are recommended always to check for a stack overflow, regardless
of the failing instruction. To reduce the possibility of a JVM crash, you must set an
appropriate native stack size when you run a Java program using a lot of native
stack.
(dbx) thread info 1
thread state-k wchan state-u k-tid mode held scope function
>$t1 run running 85965 k no sys oflow
general:
pthread addr = 0x302027e8 size = 0x22c
vp addr = 0x302057e4 size = 0x294
thread errno = 0
start pc = 0x10001120
joinable = yes
pthread_t = 1
scheduler:
kernel =
user = 1 (other)
event :
event = 0x0
cancel = enabled, deferred, not pending
stack storage:
base = 0x2df23000
size = 0x1fff7b0
limit = 0x2ff227b0
sp = 0x2df2cc70
For the second cause, currently dbx (and therefore stackit.sh) does not understand
the structure of the JIT and Interpreter stack frames, and is not capable of
generating a stack trace from them. The javadump, however, does not suffer from
this limitation and can be used to examine the stack trace.
108 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - debugging hangs
Debugging hangs
The JVM is hanging if the process is still present but is not responding in some
sense. This lack of response can be caused because:
v The process has come to a complete halt because of a deadlock condition
v The process has become caught in an infinite loop
v The process is running very slowly
AIX deadlocks
For an explanation of deadlocks and how the Javadump tool is used to diagnose
them, see “Locks, monitors, and deadlocks (LOCKS)” on page 193.
If the process is not taking up any CPU time, it is deadlocked. Use the ps -fp
[process id] command to investigate whether the process is still using CPU time.
The ps command is described in “AIX debugging commands” on page 97. For
example:
$ ps -fp 30450
UID PID PPID C STIME TTY TIME CMD
root 30450 32332 2 15 May pts/17 12:51 java ...
If the value of ’TIME’ increases over the course of a few minutes, the process is
still using the CPU and is not deadlocked.
The third reason, where threads are waiting (for instance, on sockets) for I/O,
requires further investigation. Has the process at the other end of the I/O failed?
Do any network problems exist?
To see how the javadump tool is used to diagnose loops, see “Locks, monitors, and
deadlocks (LOCKS)” on page 193. If you cannot diagnose the problem from the
javadump and if the process still seems to be using processor cycles, either it has
entered an infinite loop or it is suffering from very bad performance. Using ps -mp
[process id] -o THREAD allows individual threads in a particular process to be
monitored to determine which threads are using the CPU time. If the process has
entered an infinite loop, it is likely that a small number of threads will be using
the time. For example:
$ ps -mp 43824 -o THREAD
USER PID PPID TID ST CP PRI SC WCHAN F TT BND COMMAND
wsuser 43824 51762 - A 66 60 77 * 200001 pts/4 - java ...
- - - 4021 S 0 60 1 22c4d670 c00400 - - -
- - - 11343 S 0 60 1 e6002cbc 8400400 - - -
- - - 14289 S 0 60 1 22c4d670 c00400 - - -
- - - 14379 S 0 60 1 22c4d670 c00400 - - -
...
- - - 43187 S 0 60 1 701e6114 400400 - - -
Those threads with the value ’R’ under ’ST’ are in the ’runnable’ state, and
therefore are able to accumulate processor time. What are these threads doing? The
output from ps shows the TID (Kernel Thread ID) for each thread. This can be
mapped to the Java thread ID using dbx. The output of the dbx thread command
gives an output of the form of:
thread state-k wchan state-u k-tid mode held scope function
$t1 wait 0xe60196bc blocked 104099 k no sys _pthread_ksleep
>$t2 run blocked 68851 k no sys _pthread_ksleep
$t3 wait 0x2015a458 running 29871 k no sys pthread_mutex_lock
...
$t50 wait running 86077 k no sys getLinkRegister
$t51 run running 43939 u no sys reverseHandle
$t52 wait running 56273 k no sys getLinkRegister
$t53 wait running 37797 k no sys getLinkRegister
$t60 wait running 4021 k no sys getLinkRegister
$t61 wait running 18791 k no sys getLinkRegister
$t62 wait running 99345 k no sys getLinkRegister
$t63 wait running 20995 k no sys getLinkRegister
By matching the TID value from ps to the k-tid value from the dbx thread
command, you can see that the currently running methods in this case are
reverseHandle and getLinkRegister.
Now you can use dbx to generate the C thread stack for these two threads using
the dbx thread command for the corresponding dbx thread numbers ($tx). To
obtain the full stack trace including Java frames, map the dbx thread number to
the threads pthread_t value, which is listed by the Javadump file, and can be
obtained from the ExecEnv structure for each thread using the Dump Viewer. Do
this with the dbx command thread info [dbx thread number], which produces an
output of the form:
thread state-k wchan state-u k-tid mode held scope function
$t51 run running 43939 u no sys reverseHandle
general:
pthread addr = 0x220c2dc0 size = 0x18c
vp addr = 0x22109f94 size = 0x284
thread errno = 61
start pc = 0xf04b4e64
joinable = yes
pthread_t = 3233
scheduler:
kernel =
user = 1 (other)
event :
event = 0x0
cancel = enabled, deferred, not pending
stack storage:
base = 0x220c8018 size = 0x40000
limit = 0x22108018
sp = 0x22106930
110 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - debugging hangs
Showing that the TID value from ps (k-tid in dbx) corresponds to dbx thread
number 51, which has a pthread_t of 3233. Looking for the pthread_t in the
Javadump file, you now have a full stack trace:
"Worker#31" (TID:0x36288b10, sys_thread_t:0x220c2db8) Native Thread State:
ThreadID: 00003233 Reuse: 1 USER SUSPENDED Native Stack Data : base: 22107f80
pointer 22106390 used(7152) free(250896)
----- Monitors held -----
java.io.OutputStreamWriter@3636a930
com.ibm.servlet.engine.webapp.BufferedWriter@3636be78
com.ibm.servlet.engine.webapp.WebAppRequestDispatcher@3636c270
com.ibm.servlet.engine.srt.SRTOutputStream@36941820
com.ibm.servlet.engine.oselistener.nativeEntry.NativeServerConnection@36d84490 JNI pinning lock
com.ibm.servlet.engine.oselistener.nativeEntry.NativeServerConnection.write(Compiled Code)
com.ibm.servlet.engine.srp.SRPConnection.write(Compiled Code)
com.ibm.servlet.engine.srt.SRTOutputStream.write(Compiled Code)
java.io.OutputStreamWriter.flushBuffer(Compiled Code)
java.io.OutputStreamWriter.flush(Compiled Code)
java.io.PrintWriter.flush(Compiled Code)
com.ibm.servlet.engine.webapp.BufferedWriter.flushChars(Compiled Code)
com.ibm.servlet.engine.webapp.BufferedWriter.write(Compiled Code)
java.io.Writer.write(Compiled Code)
java.io.PrintWriter.write(Compiled Code)
java.io.PrintWriter.write(Compiled Code)
java.io.PrintWriter.print(Compiled Code)
java.io.PrintWriter.println(Compiled Code)
pagecompile._identifycustomer_xjsp.service(Compiled Code)
javax.servlet.http.HttpServlet.service(Compiled Code)
com.ibm.servlet.jsp.http.pagecompile.JSPState.service(Compiled Code)
com.ibm.servlet.jsp.http.pagecompile.PageCompileServlet.doService(Compiled Code)
com.ibm.servlet.jsp.http.pagecompile.PageCompileServlet.doGet(Compiled Code)
javax.servlet.http.HttpServlet.service(Compiled Code)
javax.servlet.http.HttpServlet.service(Compiled Code)
And, using the full stack trace, it should be possible to identify any infinite loop
that might be occurring. The above example shows the use of
spin_lock_global_common, which is a busy wait on a lock, hence the use of CPU
time.
Kernel 0x0
0x3
0x4
0x5
0x6
0x7
Shared memory and mmap services
0x8
0x9
0xA
0xB
0xC
112 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - understanding memory usage
With the large address space available to the 64-bit process, you are unlikely to
encounter the same kind of problems with relation to native heap usage as
described later in this chapter, although you might still suffer from a leak in the
native heap.
| Further details of the AIX Memory Models can be found at: http://
| publib.boulder.ibm.com/infocenter/pseries/....
The Java heap contains the instances of Java objects and is often referred to simply
as ’the heap’. It is the Java heap that is maintained by Garbage Collection, and it is
the Java heap that is changed by the command-line heap settings. The Java heap is
allocated using mmap, or shmat if large page support is requested. The maximum
size of the Java heap is preallocated during JVM startup as one contiguous area,
even if the minimum heap size setting is lower. This allocation allows the artificial
heap size limit imposed by the minimum heap size setting to move toward the
actual heap size limit with heap expansion. See Chapter 2, “Understanding the
Garbage Collector,” on page 7 for more information.
The native, or system heap, is allocated by using the underlying malloc and free
mechanisms of the operating system, and is used for the underlying
implementation of particular Java objects; for example:
v Motif objects required by AWT and Swing
v Buffers for Inflaters and Deflators
v Malloc allocations by application JNI code
v Compiled code generated by the Just In Time (JIT) Compiler
v Threads to map to Java threads
| Because the Java heap is allocated using mmap() or shmat(), it is clear whether
| memory allocated to a specific segment of memory (under ’Esid’) is allocated to
| the Java or the native heap. The type and description fields for each of the
| segments allows the determination of which sections are native or Java heap.
| Segments allocated using mmap or shmat are listed as ″mmap mapped to″ or
| ″extended shm segments″ and are the Java heap. Segments allocated using malloc
| will be marked as ″working storage″ and are in the native heap. This demarcation
| makes it possible to monitor the growth of the native heap separately from the
| Java heap (which should be monitored using verbose GC).
Here is the svmon output from the command that is shown above:
114 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - understanding memory usage
| -------------------------------------------------------------------------------
| Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd LPage
| 29670 java 87347 4782 5181 95830 N Y N
|
| Vsid Esid Type Description LPage Inuse Pin Pgsp Virtual
| 50e9 - work - 41382 0 0 41382
| Addr Range: 0..41381
| 9dfb - work - 28170 0 2550 30720
| Addr Range: 0..30719
| ddf3 3 work working storage - 9165 0 979 10140
| Addr Range: 0..16944
| 0 0 work kernel seg - 5118 4766 1322 6420
| Addr Range: 0..11167
| c819 d work text or shared-lib code seg - 2038 0 283 6813
| Addr Range: 0..10219
| 2ded f work working storage - 191 0 20 224
| Addr Range: 0..4150
| f5f6 - work - 41 14 4 45
| Addr Range: 0..49377
| 6e05 2 work process private - 35 2 23 58
| Addr Range: 65296..65535
| 1140 6 work other segments - 26 0 0 26
| Addr Range: 0..32780
| cdf1 - work - 2 0 0 2
| Addr Range: 0..5277
| e93f - work - 0 0 0 0
| 3164 c mmap mapped to sid 1941 - 0 0 - -
| 2166 - work - 0 0 0 0
| 496b b mmap mapped to sid 2166 - 0 0 - -
| b51e - clnt /dev/fslv00:44722 - 0 0 - -
| Addr Range: 0..207
| ee1c a mmap mapped to sid e93f - 0 0 - -
| 1941 - work - 0 0 0 0
| 1081 7 mmap mapped to sid 9dfb - 0 0 - -
| edf5 8 mmap mapped to sid 50e9 - 0 0 - -
| c01b 9 mmap mapped to sid cdf1 - 0 0 - -
| The actual memory values for the mmap allocated segments are stored against a
| Vsid of type ″work″. For example, the memory usage in segment 7 (Java heap):
| 1081 7 mmap mapped to sid 9dfb - 0 0 - -
| You can monitor the JIT compiling of code to avoid confusing this behavior with a
| memory leak. To do this, run with the command-line option
| -Xjit:verbose={compileStart|compileEnd}. This command causes each method
| name to print to stderr as it is being compiled and, as it finishes compiling, the
| location in memory where the compiled code is stored.
| (warm) Compiling java/lang/System.getEncoding(I)Ljava/lang/String;
| + (warm) java/lang/System.getEncoding(I)Ljava/lang/String; @ 0x02BA0028-0x02BA0113
| (2) Compiling java/lang/String.hashCode()I
| + (warm) java/lang/String.hashCode()I @ 0x02BA0150-0x02BA0229
| (2) Compiling java/util/HashMap.put(Ljava/lang/Object;Ljava/lang/Object;)
| Ljava/lang/Object;
| + (warm) java/util/HashMap.put(Ljava/lang/Object;Ljava/lang/Object;)
| Ljava/lang/Object; @ 0x02BA0270-0x02BA03F7
| (2) Compiling java/lang/String.charAt(I)C
| + (warm) java/lang/String.charAt(I)C @ 0x02BA0430-0x02BA04AC
| (2) Compiling java/util/Locale.toLowerCase(Ljava/lang/String;)
| Ljava/lang/String;
| + (warm) java/util/Locale.toLowerCase(Ljava/lang/String;)Ljava/lang/String;
| @ 0x02BA04D0-0x02BA064C
| When you have monitored how much native heap you are using, you can increase
| or decrease the maximum native heap available by altering the size of the Java
| heap. This relationship between the heaps occurs because the process address
| space not used by the Java heap is available for the native heap usage.
| You must increase the native heap if the process is generating errors relating to a
| failure to allocate native resources or exhaustion of process address space. These
| errors can take the form of a JVM internal error message or a detail message
| associated with an OutOfMemoryError. The message associated with the relevant
| errors will make it clear that the problem is native heap exhaustion.
Specifying MALLOCTYPE
You can set the MALLOCTYPE=watson environment variable, available in AIX 5.3,
for use with the IBM 142 JVM, but for most applications the performance gains are
likely to be small. It particularly benefits any application that makes heavy use of
malloc calls in native code. For more information, see this article:
http://www-128.ibm.com/developerworks/eserver/library/es-appdev-aix5l.html.
| where:
| [DIR_PATH] is the directory where the file should be written
| [FILE_NAME] is the name of the file to write the logging to
| See “Using VerboseGC to obtain heap information” on page 208 for more
information on verbose GC output and monitoring.
If the problem is occurring because of a real memory leak, increasing the heap size
will not solve the problem, but will delay the onset of the OutOfMemory or error
conditions, which can be of help on any production system.
116 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - understanding memory usage
If no error message is present, the first stage is to monitor the Java and native heap
usages. The Java heap usage can be monitored by using -verbose:gc as detailed
above, and the native heap using svmon.
Java heap exhaustion can be identified from the -verbose:gc output by garbage
collection occurring more and more frequently, with less memory being freed.
Eventually the JVM will fail, and the heap occupancy will be at, or almost at, 100%
(See Chapter 2, “Understanding the Garbage Collector,” on page 7 for more details
on -verbose:gc output).
If the Java heap is being exhausted, and increasing the Java heap size does not
solve the problem, the next stage is to examine the objects that are on the heap,
and look for suspect data structures that are referencing large numbers of Java
objects that should have been released. Use Heapdump Analysis, as detailed in
“Available tools for processing Heapdumps” on page 208. Similar information can
be gained by using other tools, such as JProbe and OptimizeIt.
If each of the segments has approximately 65535 Inuse pages, the process is
suffering from native heap exhaustion. At this point, extending the native heap
size might solve the problem, but you should investigate the memory usage profile
to ensure that you do not have a leak.
f DB2 is running on your AIX system, you can change the application code to use
the ″net″ (thin client) drivers and, in the case of WebSphere MQ you can use the
″client″ (out of process) drivers.
This kind of OutOfMemory condition can again be identified from the svmon
snapshots. Whereas previously the important column to look at for a memory leak
is the Inuse values, for problems in the AIX malloc heaps it is important to look at
the ’Addr Range’ column. The ’Addr Range’ column details the pages that have
been allocated, whereas the Inuse column details the number of pages that are
being used (committed).
It is possible that pages that have been allocated have not been released back to
the process when they have been freed. This leads to the discrepancy between the
number of allocated and committed pages.
You have a range of environment variables to change the behavior of the malloc
algorithm itself and thereby solve problems of this type:
MALLOCTYPE=3.1
This option allows the system to move back to an older version of memory
allocation scheme in which memory allocation is done in powers of 2. The 3.1
Malloc allocator, as opposed to the default algorithm, frees pages of memory
back to the system for reuse. The 3.1 allocation policy is available for use only
with 32-bit applications.
MALLOCMULTIHEAP=heaps:n,considersize
By default, the malloc subsystem uses a single heap. MALLOCMULTIHEAP
allows users to enable the use of multiple heaps of memory. Multiple heaps of
memory can lead to memory fragmentation, and so the use of this
environment variable is not recommended
MALLOCTYPE=buckets
Malloc buckets provides an optional buckets-based extension of the default
allocator. It is intended to improve malloc performance for applications that
issue large numbers of small allocation requests. When malloc buckets is
enabled, allocation requests that fall within a predefined range of block sizes
are processed by malloc buckets. Because of variations in memory
requirements and usage, some applications might not benefit from the memory
allocation scheme used by malloc buckets. Therefore, it is not advisable to
enable malloc buckets system-wide. For optimal performance, enable and
configure malloc buckets on a per-application basis.
Note: The above options might cause a percentage of performance hit. Also
the 3.1 malloc allocator does not support the Malloc Multiheap and
Malloc Buckets options.
MALLOCBUCKETS=number_of_buckets:128,bucket_sizing_factor:64,blocks_per_
bucket:1024: bucket_statistics: pathname of file for malloc statistics>
See above.
118 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - understanding memory usage
v As appropriate:
1. The svmon snapshot output
2. The Heapdump output
| 3. The javacore.txt file
Correcting one performance problem might cause more problems in another area.
By finding and correcting a bottleneck in one place you might only shift the cause
of poor performance to other areas. To improve performance, experiment with
tuning different parameters, monitoring the effect, and retuning until you are
satisfied that your system is performing acceptably
Given that any performance problem could be caused by any one of several
factors, you must look at several areas to eliminate each one. First, determine
which resource is constraining the system:
v CPU
v Memory
v Input/Output (I/O)
To do this, use the vmstat command. The vmstat command produces a compact
report that details the activity of these three areas:
> vmstat 1 10
outputs:
kthr memory page faults cpu
----- ----------- ------------------------ ------------ -----------
r b avm fre re pi po fr sr cy in sy cs us sy id wa
0 0 189898 612 0 0 0 3 11 0 178 606 424 6 1 92 1
1 0 189898 611 0 1 0 0 0 0 114 4573 122 96 4 0 0
1 0 189898 611 0 0 0 0 0 0 115 420 102 99 0 0 0
1 0 189898 611 0 0 0 0 0 0 115 425 91 99 0 0 0
1 0 189898 611 0 0 0 0 0 0 114 428 90 99 0 0 0
1 0 189898 610 0 1 0 0 0 0 117 333 102 97 3 0 0
1 0 189898 610 0 0 0 0 0 0 114 433 91 99 1 0 0
1 0 189898 610 0 0 0 0 0 0 114 429 94 99 1 0 0
1 0 189898 610 0 0 0 0 0 0 115 437 94 99 0 0 0
1 0 189898 609 0 1 0 0 0 0 116 340 99 98 2 0 0
The example above shows a system that is CPU bound. This can be seen as the
user (us) plus system (sy) CPU values either equal or are approaching 100. A
system that is memory bound shows significant values of page in (pi) and page
out (po). A system that is disk I/O bound will show an I/O wait percentage (wa)
exceeding 10%. More details of vmstat can be found in “AIX debugging
commands” on page 97.
CPU bottlenecks
| If vmstat has shown that the system is CPU-bound, the next stage is to determine
| which process is using the most CPU time. The recommended tool is tprof:
| > tprof -s -k -x sleep 60
| outputs:
| Mon Nov 28 12:40:11 2005
| System: AIX 5.2 Node: voodoo Machine: 00455F1B4C00
|
| Starting Command sleep 60
| stopping trace collection
| Generating sleep.prof
| > cat sleep.prof
| Process Freq Total Kernel User Shared Other
| ======= ==== ===== ====== ==== ====== =====
| ./java 5 59.39 24.28 0.00 35.11 0.00
| wait 4 40.33 40.33 0.00 0.00 0.00
| /usr/bin/tprof 1 0.20 0.02 0.00 0.18 0.00
| /etc/syncd 3 0.05 0.05 0.00 0.00 0.00
| /usr/bin/sh 2 0.01 0.00 0.00 0.00 0.00
| gil 2 0.01 0.01 0.00 0.00 0.00
| afsd 1 0.00 0.00 0.00 0.00 0.00
| rpc.lockd 1 0.00 0.00 0.00 0.00 0.00
| swapper 1 0.00 0.00 0.00 0.00 0.00
| ======= ==== ===== ====== ==== ====== =====
| Total 20 100.00 64.70 0.00 35.29 0.00
|
| Process PID TID Total Kernel User Shared Other
| ======= === === ===== ====== ==== ====== =====
| ./java 467018 819317 16.68 5.55 0.00 11.13 0.00
| ./java 467018 766019 14.30 6.30 0.00 8.00 0.00
| ./java 467018 725211 14.28 6.24 0.00 8.04 0.00
| ./java 467018 712827 14.11 6.16 0.00 7.94 0.00
| wait 20490 20491 10.24 10.24 0.00 0.00 0.00
| wait 8196 8197 10.19 10.19 0.00 0.00 0.00
| wait 12294 12295 9.98 9.98 0.00 0.00 0.00
| wait 16392 16393 9.92 9.92 0.00 0.00 0.00
| /usr/bin/tprof 421984 917717 0.20 0.02 0.00 0.18 0.00
| /etc/syncd 118882 204949 0.04 0.04 0.00 0.00 0.00
| ./java 467018 843785 0.03 0.02 0.00 0.00 0.00
| gil 53274 73765 0.00 0.00 0.00 0.00 0.00
| gil 53274 61471 0.00 0.00 0.00 0.00 0.00
| /usr/bin/sh 397320 839883 0.00 0.00 0.00 0.00 0.00
| rpc.lockd 249982 434389 0.00 0.00 0.00 0.00 0.00
| /usr/bin/sh 397318 839881 0.00 0.00 0.00 0.00 0.00
| swapper 0 3 0.00 0.00 0.00 0.00 0.00
| afsd 65776 274495 0.00 0.00 0.00 0.00 0.00
| /etc/syncd 118882 258175 0.00 0.00 0.00 0.00 0.00
| /etc/syncd 118882 196839 0.00 0.00 0.00 0.00 0.00
| ======= === === ===== ====== ==== ====== =====
| Total 100.00 64.70 0.00 35.29 0.00
|
| Total Samples = 24749 Total Elapsed Time = 61.88s
| This output shows that the Java process with Process ID (PID) 467018 is using the
| majority of the CPU time. You can also see that the CPU time is being shared
| among four threads inside that process (Thread IDs 819317, 766019, 725211, and
| 712827).
120 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - debugging performance problems
| From the above example, notice the Kernel and Shared values: these account for all
| of the CPU time used by this process, indicating that the Java process is spending
| its time doing work inside the JVM (or some other native code).
| To understand what is being done during the Kernel and Shared times, the
| relevant sections of the tprof output can be analyzed.
| The shared library section shows which shared libraries are being invoked:
| Shared Object %
| ============= ======
| /j9vmap3223-20051123/inst.images/rios_aix32_5/sdk/jre/bin/libj9gc23.so 17.42
| /usr/lib/libc.a[shr.o] 9.38
| /usr/lib/libpthreads.a[shr_xpg5.o] 6.94
| j9vmap3223-20051123/inst.images/rios_aix32_5/sdk/jre/bin/libj9thr23.so 1.03
| j9vmap3223-20051123/inst.images/rios_aix32_5/sdk/jre/bin/libj9prt23.so 0.24
| /j9vmap3223-20051123/inst.images/rios_aix32_5/sdk/jre/bin/libj9vm23.so 0.10
| j9vmap3223-20051123/inst.images/rios_aix32_5/sdk/jre/bin/libj9ute23.so 0.06
| j9vmap3223-20051123/inst.images/rios_aix32_5/sdk/jre/bin/libj9jit23.so 0.05
| /usr/lib/libtrace.a[shr.o] 0.04
| j9vmap3223-20051123/inst.images/rios_aix32_5/sdk/jre/bin/libj9trc23.so 0.02
| p3223-20051123/inst.images/rios_aix32_5/sdk/jre/bin/libj9hookable23.so 0.01
|
| This section shows that almost all of the time is being spent in one particular
| shared library, which is part of the JVM installation: libj9gc23.so. By understanding
| the functions that the more commonly used JVM libraries carry out, it becomes
| possible to build a more accurate picture of what the threads are doing:
| libbcv23.so
| Bytecode Verifier
| libdbg23.so
| Debug Server (used by the Java Debug Interface)
| libj9gc23.so
| Garbage Collection
| libj9jextract.so
| The dump extractor, used by the jextract command
| libj9jit23.so
| The Just In Time (JIT) Compiler
| libj9jpi23.so
| The JVMPI interface
| libj9jvmti23.so
| The JVMTI interface
| libj9prt23.so
| The ″port layer″ between the JVM and the Operating System
| libj9shr23.so
| The shared classes library
| libj9thr23.so
| The threading library
| libj9ute23.so
| The trace engine
| libj9vm23.so
| The core Virtual Machine
| libj9zlib23.so
| The compressed file utility library
| libjclscae_23.so
| The Java Class Library (JCL) support routines
| In the example above, the CPU time is being spent inside the garbage collection
| (GC) implementation, implying either that there is a problem in GC or that GC is
| running almost continuously.
| Again, you can obtain a more accurate understanding of what is occurring inside
| the libj9gc23.so library during the CPU time by analyzing the relevant section of
| the tprof output:
| Profile: /work/j9vmap3223-20051123/inst.images/rios_aix32_5/sdk/jre/bin/
| libj9gc23.so
|
| Total % For All Processes (/work/j9vmap3223-20051123/inst.images/rios_aix32_5/
| sdk/jre/bin/libj9gc23.so) = 17.42
|
| Subroutine % Source
| ========== ====== ======
| Scheme::scanMixedObject(MM_Environment*,J9Object*) 2.67 MarkingScheme.cpp
| MarkingScheme::scanClass(MM_Environment*,J9Class*) 2.54 MarkingScheme.cpp
| .GC_ConstantPoolObjectSlotIterator::nextSlot() 1.96 jectSlotIterator.cpp
| lelTask::handleNextWorkUnit(MM_EnvironmentModron*) 1.05 ParallelTask.cpp
| orkPackets::getPacket(MM_Environment*,MM_Packet**) 0.70 WorkPackets.cpp
| cheme::fixupRegion(J9Object*,J9Object*,bool,long&) 0.67 CompactScheme.cpp
| WorkPackets::putPacket(MM_Environment*,MM_Packet*) 0.47 WorkPackets.cpp
| rkingScheme::scanObject(MM_Environment*,J9Object*) 0.43 MarkingScheme.cpp
| sweepChunk(MM_Environment*,MM_ParallelSweepChunk*) 0.42 allelSweepScheme.cpp
| ment*,J9IndexableObject*,J9Object**,unsigned long) 0.38 MarkingScheme.cpp
| M_CompactScheme::getForwardingPtr(J9Object*) const 0.36 CompactScheme.cpp
| ObjectHeapIteratorAddressOrderedList::nextObject() 0.33 dressOrderedList.cpp
| ckets::getInputPacketFromOverflow(MM_Environment*) 0.32 WorkPackets.cpp
| .MM_WorkStack::popNoWait(MM_Environment*) 0.31 WorkStack.cpp
| WorkPackets::getInputPacketNoWait(MM_Environment*) 0.29 WorkPackets.cpp
| canReferenceMixedObject(MM_Environment*,J9Object*) 0.29 MarkingScheme.cpp
| MarkingScheme::markClass(MM_Environment*,J9Class*) 0.27 MarkingScheme.cpp
122 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - debugging performance problems
| The values show that the time is being spent during the Mark phase of GC.
| Because the output also contains references to the Compact and Sweep phases, it is
| likely that GC is completing but that it is occurring continuously. You could
| confirm that likelihood by running with -verbosegc enabled.
| The same methodology shown above can be used for any case where the majority
| of the CPU time is shown to be in the Kernel and Shared columns. If, however, the
| CPU time is classed as being ″Other″, a different methodology is required because
| tprof does not contain a section that correctly details which Java methods are being
| run.
| In the case of CPU time being attributed to ″Other″, you can use a javacore file (or
| a series of javacore files) to determine the stack trace for the TIDs shown to be
| taking the CPU time, and therefore provide an idea of the work that it is doing.
| Map the value of TID shown in the tprof output to the correct thread in the
| javacore file by taking the tprof TID, which is stored in decimal, and convert it to
| hexadecimal. The hexadecimal value is shown as the ″native ID″ in the javacore
| file.
| This thread is the one using the most CPU; the TID in decimal is 819317. This
| value is C8075 in hexadecimal, which can be seen in the javacore file:
| 3XMTHREADINFO "main" (TID:0x300E3500, sys_thread_t:0x30010734,
| state:R, native ID:0x000C8075) prio=5
| 4XESTACKTRACE at java/lang/Runtime.gc(Native Method)
| 4XESTACKTRACE at java/lang/System.gc(System.java:274)
| 4XESTACKTRACE at GCTest.main(GCTest.java:5)
| These entries show that, in this case, the thread is calling GC, and explains the
| time spent in the libj9gc23.so shared library.
Memory bottlenecks
If the results of vmstat point to a memory bottleneck, you must find out which
processes are using large amounts of memory, and which, if any, of these are
growing. Use the svmon tool:
> svmon -P -t 5
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd
38454 java 76454 1404 100413 144805 N Y
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd
15552 X 14282 1407 17266 19810 N N
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd
14762 dtwm 3991 1403 5054 7628 N N
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd
15274 dtsessi 3956 1403 5056 7613 N N
-------------------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd
21166 dtpad 3822 1403 4717 7460 N N
This output shows that the highest memory user is Java, and that it is using 144805
pages of virtual memory (144805 * 4 KB = 565.64 MB). This is not an unreasonable
amount of memory for a JVM with a large Java heap - in this case 512 MB.
If the system is memory-constrained with this level of load, the only remedies
available are either to obtain more physical memory or to attempt to tune the
amount of paging space that is available by using the vmtune command to alter
the maxperm and minperm values.
If the Java process continues to increase its memory usage, an eventual memory
constraint will be caused by a memory leak.
I/O bottlenecks
This book does not discuss conditions in which the system is disk- or
network-bound. For disk-bound conditions, use filemon to generate more details of
which files and disks are in greatest use. For network conditions, use netstat to
determine network traffic. A good resource for these kinds of problems is
Accelerating AIX by Rudy Chukran (Addison Wesley, 1998).
Application profiling
You can learn a lot about your Java application by using the hprof profiling agent.
Statistics about CPU and memory usage are presented along with many other
options. The hprof tool is discussed in detail in Chapter 32, “Using the JVMPI,” on
page 297. -Xrunhprof:help gives you a list of suboptions that you can use with
hprof.
124 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
AIX - collecting data from a fault condition
http://techsupport.services.ibm.com/server/nav?fetch=a4ojc
http://techsupport.services.ibm.com/server/nav?fetch=a5oj
126 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 15. Linux problem determination
This chapter describes problem determination on Linux in:
v “Setting up and checking your Linux environment”
v “General debugging techniques” on page 128
v “Diagnosing crashes” on page 134
v “Debugging hangs” on page 135
v “Debugging memory leaks” on page 135
v “Debugging performance problems” on page 135
v “Collecting data from a fault condition in Linux” on page 138
v “Known limitations on Linux” on page 140
The Java service team has a tool named ReportEnv that plugs into your JVM and
reports on the JVM environment in real time. Your JVM environment affects the
operation of the JVM. ReportEnv reports on environment variables and
command-line parameters. It is a GUI tool, although it can be run without a GUI.
The GUI allows you to browse your environment and, to some extent, dynamically
change it. The tool also has a mechanism to generate reports to tell you the exact
state of your JVM environment. A screenshot of the tool is shown in “Setting up
and checking your Windows environment” on page 143. The ReportEnv tool is
available on request from [email protected].
Working directory
The current working directory of the JVM process is where core files, Java dumps,
heap dumps, and the JVM trace outputs, including Application Trace and Method
trace, are outputted. Enough free disk space must be available for this directory.
Also, the JVM must have write permission.
Because truncated files are of no practical use, set the size of the Linux core file to
″unlimited″.
Table 5. Usage of ulimit
Usage Action
ulimit -c # check the current corefile limit
The core file is placed into the current working directory of the process, subject to
write permissions for the JVM process and free disk space.
Depending on the kernel level, a useful kernel option is available that gives
corefiles more meaningful names. As root user, the option sysctl -w
kernel.core_users_pid=1 ensures that core files have a name of the form
″Core.PID″.
Threading libraries
Most Linux distributions provide an implementation of the POSIX threads
standard known as the LinuxThreads library. Some newer distributions (for
example RHEL3 and SLES9) now provide the enhanced Native POSIX Threads
Library for Linux (NPTL). For information on the threading libraries which are
supported by the IBM Virtual Machine for Java on specific Linux platforms, see
http://www.ibm.com/developerworks/java/jdk/linux/tested.html.
You can discover your glibc version by changing to the /lib directory and running
the file libc.so.6. The Linux command ldd prints information that should help you
to work out the shared library dependency of your application.
128 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Linux - general debugging techniques
This command produces a modified core file with a .sdff file extension, which you
might be asked to send to IBM service. See Chapter 26, “Using the dump
formatter,” on page 223 for details of the Cross Platform Dump Formatter.
You can see a complete list of options by typing objdump -H. The -d option
disassembles contents of executable sections
Run these commands on the same machine as the one that produced the core files
to get the most accurate symbolic information available. This output (together with
the core file, if small enough) is used by IBM Java Support to diagnose a problem.
The ps command displays process status. Use it to gather information about native
threads. Some useful options are:
v -e: Select all processes
v -l: Displays in long format
v -f: Displays a full listing
The top command displays the most CPU- or memory-intensive processes in real
time. It provides an interactive interface for manipulation of processes and allows
sorting by different criteria, such as CPU usage or memory usage. The display is
updated every five seconds by default, although this can be changed by using the
s (interactive) command. The top command displays several fields of information
for each process. The process field shows the total number of processes that are
running, but breaks this down into tasks that are running, sleeping, stopped, or
undead. In addition to displaying PID, PPID, and UID, the top command displays
information on memory usage and swap space. The mem field shows statistics on
memory usage, including available memory, free memory, used memory, shared
memory, and memory used for buffers. The Swap field shows total swap space,
available swap space, and used swap space.
The processes section shows how many processes are awaiting run time, blocked,
or swapped out.
The memory section shows the amount of memory (in kilobytes) swapped, free,
buffered, and cached. If the free memory is going down during certain stages of
your applications execution, there might be a memory leak.
The swap section shows the kilobytes per second of memory swapped in from and
swapped out to disk. Memory is swapped out to disk if RAM is not big enough to
store it all. Large values here can be a hint that not enough RAM is available
(although it is normal to get swapping when the application first starts).
The io section shows the number of blocks per second of memory sent to and
received from block devices.
The system section displays the interrupts and the context switches per second.
There is overhead associated with each context switch so a high value for this may
mean that the program does not scale well.
The cpu section shows a break down of processor time between user time, system
time, and idle time. The idle time figure shows how busy a processor is, with a
low value indicating that the processor is very busy. You can use this knowledge to
help you understand which areas of your program are using the CPU the most.
In Linux, each native thread is a distinct process with a unique process ID (PID).
The kernel can therefore provide very useful information about your threads
through commands such as ps and top.
130 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Linux - general debugging techniques
Tracing
Tracing is a technique that presents details of the execution of your program. If
you are able to follow the path of execution, you will gain a better insight into
how your program runs and interacts with its environment. Also, you will be able
to pinpoint locations where your program starts to deviate from its expected
behavior.
Three tracing tools on Linux are strace, ltrace and mtrace. The command man
<strace> will show a full set of available options.
strace
The strace tool traces system calls. You can either use it on a process that is
already active, or start it with a new process. strace records the system calls
made by a program and the signals received by a process. For each system call,
the name, arguments, and return value are used. strace allows you to trace a
program without requiring the source (no recompilation is required). If you use
it with the -f option, it will trace child processes that have been created as a
result of a forked system call. strace is often used to investigate plug-in
problems or to try to understand why programs do not start properly.
ltrace
The ltrace tool is distribution-dependent. It is very similar to strace. This tool
intercepts and records the dynamic library calls as called by the executing
process. strace does the same for the signals received by the executing process.
mtrace
mtrace is included in the GNU toolset. It installs special handlers for malloc,
realloc, and free, and enables all uses of these functions to be traced and
recorded to a file. This tracing decreases program efficiency and should not be
enabled during normal use. To use mtrace, set IBM_MALLOCTRACE to 1,
and set MALLOC_TRACE to point to a valid file where the tracing
information will be stored. You must have write access to this file.
gdb
The GNU debugger (gdb) allows you to examine the internals of another program
while the program executes or retrospectively to see what a program was doing at
the moment that it crashed. The gdb allows you to examine and control the
execution of code and is very useful for evaluating the causes of crashes or general
incorrect behavior. gdb does not handle Java processes, so it is of limited use on a
pure Java program. It is useful for debugging native libraries and the JVM itself.
Then you receive a gdb prompt, and you supply the run command and the
Java arguments:
r<java_arguments>
Attaching to a running program
If a Java program is already running, you can control it under gdb. The
process id of the running program is required, and then gdb is started with the
Java executable as the first argument and the pid as the second argument:
gdb <Java Executable> <PID>
When gdb is attached to a running program, this program is halted and its
position within the code is displayed for the viewer. The program is then
under the control of gdb and you can start to issue commands to set and view
the variables and generally control the execution of the code.
Running on a corefile
A corefile is normally produced when a program crashes. gdb can be run on
this corefile. The corefile contains the state of the program when the crash
occurred. Use gdb to examine the values of all the variables and registers
leading up to a crash. With this information, you should be able to discover
what caused the crash. To debug a corefile, invoke gdb with the Java
executable as the first argument and the corefile name as the second argument:
gdb <Java Executable> <corefile>
When you run gdb against a corefile, it will initially show information such as
the termination signal the program received, the function that was executing at
the time, and even the line of code that generated the fault.
When a program comes under the control of gdb, a welcome message is displayed
followed by a prompt (gdb). The program is now waiting for your input and will
continue in whichever way you choose.
There are a number of ways of controlling execution and examination of the code.
Breakpoints can be set for a particular line or function using the command:
breakpoint linenumber
or
breakpoint functionName
After you have set a breakpoint, use the continue command to allow the program
to execute until it hits a breakpoint.
Set breakpoints using conditionals so that the program will halt only when the
specified condition is reached. For example, using breakpoint 39 if var = = value
causes the program to halt on line 39 only if the variable is equal to the specified
value.
132 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Linux - general debugging techniques
If you want to know where as well as when a variable became a certain value you
can use a watchpoint. Set the watchpoint when the variable in question is in scope.
After doing so, you will be alerted whenever this variable attains the specified
value. The syntax of the command is: watch var = = value.
To see which breakpoints and watchpoints are set, use the info command:
info break
info watch
When gdb reaches a breakpoint or watchpoint, it prints out the line of code it is
next set to execute. Note that setting a breakpoint on line 8 will cause the program
to halt after completing execution of line 7 but before execution of line 8. As well
as breakpoints and watchpoints, the program also halts when it receives certain
system signals. By using the following commands, you can stop the debugging
tool halting every time it receives these system signals:
When the correct position of the code has been reached, there are a number of
ways to examine the code. The most useful is backtrace (abbreviated to bt), which
shows the call stack. The call stack is the collection of function frames, where each
function frame contains information such as function parameters and local
variables. These function frames are placed on the call stack in the order that they
are executed (the most recently called function appears at the top of the call stack),
so you can follow the trail of execution of a program by examining the call stack.
When the call stack is displayed, it shows a frame number to the very left,
followed by the address of the calling function, followed by the function name and
the source file for the function. For example:
To view more in-depth information about a function frame, use the frame
command along with a parameter specifying the frame number. After you have
selected a frame, you can display its variables using the command print var.
Use the print command to change the value of a variable; for example, print var
= newValue.
The info locals command displays the values of all local variables in the selected
function.
To follow the exact sequence of execution of your program, use the step and next
commands. Both commands take an optional parameter specifying the number of
lines to execute, but while next treats function calls as a single line of execution,
step will step through each line of the called function.
When you have finished debugging your code, the run command causes the
program to run through to its end or its crash point. The quit command is used to
exit gdb.
info share
Prints the names of the shared libraries that are currently loaded.
info functions
Prints all the function prototypes.
list
Shows the 10 lines of source code around the current line.
help
The help command displays a list of subjects, each of which can have the help
command invoked on it, to display detailed help on that topic.
Diagnosing crashes
Many approaches are possible when you are trying to determine the cause of a
crash. The process normally involves isolating the problem by checking the system
setup and trying various diagnostic options.
Analyze the core file (as described in Chapter 26, “Using the dump formatter,” on
page 223) to produce a stack trace, which will show what was running up to the
point of the crash. This could be:
v JNI native code.
v JIT compiled code. If you have a problem with the JIT, try running with JIT off
by setting the -Xint option.
v JVM code.
Other tracing methods:
v ltrace
v strace
v mtrace - can be used to track memory calls and determine possible corruption
v RAS trace, described in Chapter 31, “Using the Reliability, Availability, and
Serviceability Interface,” on page 283.
Use the verbosegc option to look at the state of the Java heap and determine if:
v There was a shortage of Java heap space and if this could have caused the crash.
134 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Linux - diagnosing crashes
For more information about the Garbage Collector, see Chapter 2, “Understanding
the Garbage Collector,” on page 7.
Debugging hangs
For an explanation of deadlocks and diagnosing them using the Javadump tool,
see “Locks, monitors, and deadlocks (LOCKS)” on page 193.
For more details about analyzing the Java Heap, see Chapter 22, “Using
Heapdump,” on page 205.
System performance
Several tools are available that enable you to measure system components and
establish how they are performing and under what kind of workload. Although
most of these tools have been introduced earlier in this chapter, it is still worth
mentioning them here, and discussing how you can use them to specifically debug
performance issues.
The aspects of the system that you are most interested in measuring are CPU
usage and memory usage. If you can prove that the CPU is not powerful enough
to handle the workload, any amount of tuning makes not much difference to
overall performance. Nothing less than a CPU upgrade might be required.
Similarly, if a program is running in an environment in which it does not have
enough memory, an increase in the memory is going to make a much bigger
change to performance than any amount of tuning does.
CPU usage
You might typically experience Java processes consuming 100% of processor time
when a process reaches its resource limits. Ensure that ulimit settings are
appropriate to the application requirement. Some of the most-used ulimit
parameters are discussed in Table 5 on page 127.
The /proc file system provides information about all the processes that are running
on your system, including the Linux kernel. Because Java threads are run as
system processes, you can learn valuable information about the performance of
your application. See /proc man for more information about viewing /proc
information. /proc/version gives you information about the Linux kernel that is
on your system.
The top command provides real-time information about your system processes.
The top command is useful for getting an overview of the system load. It quite
clearly displays which processes are using the most resources. Having identified
the processes that are probably causing a degraded performance, you can take
further steps to improve the overall efficiency of your program. More information
is provided about the top command in “Using system logs” on page 129.
Memory usage
If a system is performing poorly because of lack of memory resources, it is
memory bound. By viewing the contents of /proc/meminfo, you can view your
memory resources and see how they are being used. /proc/swap gives
information on your swap file.
Swap space is used as an extension of the systems virtual memory. Therefore, not
having enough memory or swap space causes performance problems. A general
guideline is that swap space should be at least twice as large as the physical
memory.
A swap space can be either a file or disk partition. A disk partition offers better
performance than a file does. fdisk and cfdisk are the commands that you use to
create another swap partition. It is a good idea to create swap partitions on
different disk drives because this distributes the I/O activities and so reduces the
chance of further bottlenecks.
VMstat is a tool that enables you to discover where performance problems might
be caused. For example, if you see that high swap rates are occurring, it is likely
that you do not have enough physical or swap space. The free command displays
your memory configuration, while swapon -s displays your swap device
configuration. A high swap rate (for example, many page faults) means that it is
quite likely that you need to increase your physical memory. More details on how
to use VMstat are provided in “Using system logs” on page 129.
136 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Linux - debugging performance problems
Network problems
Another area that often affects performance is the network. Obviously, the more
you know about the behavior of your program, the easier it is for you to decide
whether this is a likely source of performance bottleneck. If you think that your
program is likely to be I/O bound, netstat is a useful tool. In addition to providing
information about network routes, netstat gives a list of active sockets for each
network protocol and can give overall statistics, such as the number of packets that
are received and sent. Using netstat, you can see how many sockets are in a
CLOSE_WAIT or ESTABLISHED state and you can tune the respective TCP/IP
parameters accordingly for better performance of the system. For example, tuning
/proc/sys/net/ipv4/tcp_keepalive_time will reduce the time for socket waits in
TIMED_WAIT state before closing a socket. If you are tuning /proc/sys/net file
system, the effect will be on all the applications running on the system. However,
to make a change to an individual socket or connection, you have to use Java
Socket API calls (on the respective socket object). Use netstat -p (or the lsof
command) to find the right PID of a particular socket connection and its stack
trace from a javacore file taken with the kill -3 <pid> command.
You can also use IBM’s RAS trace, -Xtrace:print=net, to trace out network-related
activity within the JVM. This technique is helpful when socket-related Java thread
hangs are seen. Correlating output from netstat -p, lsof, JVM net trace, and ps
-efH can help you to diagnose the network-related problems.
Providing summary statistics that are related to your network is useful for
investigating programs that might be underperforming because of TCP/IP
problems. The more you understand your hardware capacity, the easier it is for
you to tune with confidence the parameters of particular system components that
will improve the overall performance of your application. You can also determine
whether only system tuning and tweaking will noticeably improve performance, or
whether actual upgrades are required.
JVM performance
In addition to looking at your overall hardware and system performance, you can
tune several JVM parameters to further increase performance of your Java
application. These parameters are normally set as Java command-line options.
java [-options] class [args...]
OR
java -jar [-options] jarfile [args...]
The Java heap size is one of the most important tunable parameters of your JVM.
It is especially important if you are running several processes and JVMs on your
system. The heap contains all Java objects (live and dead) and free memory.
Garbage collection is based on how full your heap is. Therefore, a large heap size
delays the frequency of garbage collection, but when garbage collection does occur,
it takes longer to complete.
What you consider to be an acceptable heap size depends on your application; you
will certainly need to experiment. In addition to balancing the frequency and
length of garbage collections, you must also remember that memory that is
allocated to one applications heap is not available to other applications. This is an
example of fixing a bottleneck in one area, by increasing heap size to decrease
frequency of garbage collection, and causing problems somewhere else. For
example, other processes might have to use paging to supplement their diminished
memory. Under no circumstances should heap size be larger than physical
memory.
-Xms sets the initial heap size and -Xmx sets the maximum heap size.
After you have set the heap size, the verbosegc command shows you information
about garbage collection. The default garbage collection policy is optthruput,
which generally gives the fastest throughput. However, by specifying optavgpause,
you can help programs that are displaying erratic response times, although
throughput will be slower. See Chapter 28, “Garbage Collector diagnostics,” on
page 241 for more information.
JIT
The JIT is another area that can affect the performance of your program. When
deciding whether to use JIT compilation, you must make a balance between faster
execution and increased compilation overhead. The JIT is on by default; you can
turn it off by using -Xint.
It is useful to investigate the JIT when you are debugging performance problems.
For more details about the JIT, see Chapter 4, “Understanding the JIT,” on page 29
and Chapter 27, “JIT problem determination,” on page 237.
You can learn much about your Java application by using hprof, the nonstandard
profiling agent. Statistics about CPU and memory usage are presented along with
many other options. The hprof tool is discussed in detail in Chapter 32, “Using the
JVMPI,” on page 297. -Xrunhprof:help gives you a list of suboptions that you can
use with hprof.
Producing Javadumps
In some conditions (a crash, for example), a Javadump is produced, usually in the
current directory. In others (for example, a hang) you might have to prompt the
JVM for this by sending the JVM a SIGQUIT (kill -3 <PID>) signal. This is
discussed in more detail in Chapter 21, “Using Javadump,” on page 191.
138 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
collecting data from a fault condition in Linux
In general, the uname, df, and free output is useful. The other commands may be
run before and after a crash or during a hang to determine the state of a process
and to provide useful diagnostic information.
The following command builds an archive from files {file1,..,fileN} and compresses
them to a file whose name has the format filename.tar.gz:
tar czf filename.tgz file1 file2...filen
The command cat /proc/N/maps lists memory segments (including native heap)
for a given process.
Threads as processes
The JVM for Linux implements Java threads as native threads. On NPTL-enabled
systems such as RHEL3 and SLES9, these are implemented as threads. However
using the LinuxThreads library results in each thread being a separate Linux
process. If the number of Java threads exceeds the maximum number of processes
allowed, your program might:
v Get an error message
v Get a SIGSEGV error
v Hang
Before kernel 2.4, the maximum number of threads available is determined by the
minimum of:
v The user processes setting (ulimit -u) in /etc/security/limits.conf.
v The limit MAX_TASKS_PER_USER defined in /usr/include/linux/tasks.h.
(This change requires the Linux kernel to be recompiled.)
v The limit PTHREAD_THREADS_MAX defined in libpthreads.so. (This change
requires the Linux kernel to be recompiled.)
However, you might run out of virtual storage before reaching the maximum
number of threads.
In kernel 2.4, the native stack size is the main limitation when running a large
number of threads. Use the -Xss option to reduce the size of the thread stack so
that the JVM can handle the required number of threads. For example, set the stack
size to 32 KB on startup.
glibc limitations
If you receive a message indicating that the libjava.so library could not be loaded
because of a symbol not found (such as __bzero), you might have a down-level
version of the GNU C Runtime Library, glibc, installed. The SDK for Linux thread
implementation requires glibc version 2.1 or greater.
140 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Known limitations on Linux
Font limitations
When you are installing on a Red Hat system, to allow the font server to find the
Java TrueType fonts, run:
/usr/sbin/chkfontpath --add /opt/IBMJava2-131/jre/lib/fonts
You must do this at install time and you must be logged on as ″root″ to run the
command. For more detailed font issues, particularly with regard to Japanese fonts,
see the User Guide for your SDK.
CORBA limitations
Bidirectional GIOP is not supported.
142 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 16. Windows problem determination
The Windows SDK is available only internally to IBM for testing purposes. This
chapter describes problem determination on Windows in:
v “Setting up and checking your Windows environment”
v “General debugging techniques” on page 145
v “Diagnosing crashes in Windows” on page 146
v “Debugging hangs” on page 147
v “Debugging memory leaks” on page 147
v “Debugging performance problems” on page 149
v “Collecting data from a fault condition in Windows” on page 150
A known problem for first-time users is to install Java and then set up a work
directory and compile a ’Hello World’ program. If you cannot run HelloWorld,
possibly the CLASSPATH variable is not pointing to your .CLASS file. A solution
is to type set CLASSPATH=., which always allows you to find classes in your
current directory.
The Java service team has a tool named ReportEnv that plugs into your JVM and
reports on the JVM environment in real time. Your JVM environment affects the
operation of the JVM. ReportEnv reports on environment variables and
command-line parameters. It is a GUI tool, although it can be run without a GUI.
The GUI allows you to browse your environment and, to some extent, dynamically
change it. The tool also has a mechanism to generate reports to tell you the exact
Usage:
userdump -p
Lists all the processes and their pids.
userdump xxx
Creates a dump file of a process that has a pid of xxx (processname.dmp file is
created in the current directory from where userdump.exe is run).
For more information about generating a user dump file in a hang condition, see
“Debugging hangs” on page 147.
144 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Windows - general debugging techniques
System dump
When a JVM crash occurs, the JVM requests the operating system to generate a
system dump.
A system dump consists of all the memory that is being used by the JVM; this
includes the application heap, along with all JVM and user libraries. System
dumps allow the IBM service personnel to look at the state of the JVM at the time
of crash, and help them with the problem determination process. Because a system
dump contains all of the memory allocated by the JVM process, system dump files
can be very large.
You can find the location of the generated system dump in the output that is
displayed in the console after the crash. Here is an example of the output:
Unhandled exception
Type=GPF vmState=0x00000003
Target=2_20_20040813_1848_lHdSMR (Windows 2000 5.0 build 2195 Service Pack 4)
CPU=x86 (1 logical CPUs) (0x1ff7c000 RAM)
ExceptionCode=c0000005 ExceptionAddress=1130B074 ContextFlags=0001003f Handler1=1130B07C
Handler2=1130B080
EDI=00074af0 ESI=0000001e EAX=0006f978 EBX=00000000
ECX=00000000 EDX=00230608 EBP=0006f924
EIP=7800f4a2 ESP=0006f6cc
Module=C:\WINNT\system32\MSVCRT.dll
Module_base_address=78000000 Offset_in_DLL=0000f4a2
(I)DUMP0006 Processing Dump Event "gpf", detail "" - Please Wait.
(I)DUMP0007 JVM Requesting System Dump using ’D:\core.20040817.131302.2168.dmp’
(I)DUMP0010 System Dump written to D:\core.20040817.131302.2168.dmp
(I)DUMP0007 JVM Requesting Java Dump using ’D:\javacore.20040817.131319.2168.txt’
(I)DUMP0010 Java Dump written to D:\javacore.20040817.131319.2168.txt
(I)DUMP0013 Processed Dump Event "gpf", detail "".
In this example, the JVM has generated the dump in the file
D:\core.20040817.131302.2168.dmp.
The JVM attempts to generate the system dump file in one of the following
directories (listed in descending order):
1. The directory pointed to by environment variable IBM_COREDIR.
You might want to keep system dumps more private by setting the environment
variable IBM_COREDIR, if you are concerned about passwords and other security
details that are contained in a system dump.
Try to determine whether the application has any JNI code or uses any third-party
packages that use JNI code (for example, JDBC application drivers, and JVMPI
profiling plug-ins). If this is not the case, the fault must be in the JVM. Otherwise,
the fault must be in other code. Try and find out which is the case so that you can
pinpoint a problem.
As a general rule, try to recreate the crash with minimal dependencies (in terms of
JVM options, JNI applications, or profiling tools).
In a crash condition, gather as much data as possible for the IBM Java service
team. You should:
v Collect the Javadump. See Chapter 21, “Using Javadump,” on page 191 for more
details on using Javadump.
v Collect the crash dump. See “Setting up and checking your Windows
environment” on page 143 for details.
v Run with the JIT turned off. See Chapter 27, “JIT problem determination,” on
page 237 for details.
v If the problem occurs with or without the JIT, specify the JVM option
-Xjit:count=n. -Xjit:count=n specifies the number of times a method is invoked
before it is compiled. This way, the JVM starts up reasonably quickly (there is no
overhead of ″JITting″ all the basic methods) and keeps the advantages of having
a JIT. During the default JIT operation, some methods in your code are
interpreted and some are executed as native code, depending on whether they
have hit the threshold. If you pass the option -Xjit:count=0 to the JVM, the JIT
starts ″JITting″ all methods (that is, no code is interpreted). Run your application
with -Xjit:count=0 and collect the Javadump and the log. This is the opposite of
the previous scenario where no code was ″JIT’d″.
v Collect the Javadump log if the problem still occurs.
v Try some JIT compile options. If the problem disappears with the JIT turned off,
try some JIT compile options to see if the problem can be narrowed down
further. You could find that you can continue using the JVM, albeit with reduced
JIT performance, while giving the service team a running start with your bug
report. For information on using the basic JIT compile options, see Chapter 27,
“JIT problem determination,” on page 237.
v Try adjusting the garbage collection parameters. See Chapter 2, “Understanding
the Garbage Collector,” on page 7 for details. Make a note of any changes in
behavior.
146 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Diagnosing crashes in Windows
Debugging hangs
Hangs refer to the JVM locking-up or refusing to respond. A hang can occur when:
v Your application entered an infinite loop.
v A deadlock has occurred
To determine which of these situations applies, open the Windows Task Manager
and select the Performance tab. If the CPU time is 100% and your system is
running very slowly, the JVM is very likely to have entered an infinite loop.
Otherwise, if CPU usage is normal, you are more likely to have a deadlock
situation.
Analyzing deadlocks
For an explanation of deadlocks and diagnosing them using the Javadump tool,
see “Locks, monitors, and deadlocks (LOCKS)” on page 193.
For these conditions, the IBM Java service team can supply a small stand-alone
utility program that is called jvmdump.exe. This program takes a single parameter
that is the PID of a process. When run, the programme generates a minidump that
you can analyze through WinDbg, or translate into a dump-formatter dump in the
usual way. (See Chapter 26, “Using the dump formatter,” on page 223 for details.)
The jvmdump application is provided as-is. If you would like a copy, e-mail
[email protected].
Alternatively, if you have the Microsoft debugging tools installed, you can use
Windbg to generate a minidump. See “Generating a user dump file in a hang
condition” on page 144 for more information.
For example, the stack allocated to a thread is normally given a small amount of
actual memory. If the stack overflows, an exception is thrown and the operating
system allocates more physical memory so that the stack can grow.
From the point of view of a programmer, Windows provides a flat memory model,
in which addresses run from 0 up to the limit allowed for an application.
Applications can choose to segment their memory. On a dump, the programmer
sees sets of discrete memory addresses.
Classifying leaks
The following scenarios are possible :
v Windows memory usage is increasing, Java heap is static:
– Memory leak in application.
– Memory leak in JNI.
– Leak with hybrid Java and native objects (very rare).
v Windows memory usage increases because the heap keeps increasing:
– Memory leak in application Java code. (See “Common causes of perceived
leaks” on page 241 below.)
– Memory leak internal to JVM.
Tracing leaks
–Xrunjnichk option
You can use the -Xrunjnichk option to trace JNI calls that are made by your JNI
code or by any JVM components that use JNI. This helps you to identify incorrect
uses of JNI libraries from native code, and can help you to diagnose JNI memory
leaks. Note that -Xrunjnichk is equivalent to -Xcheck:jni. See “Debugging the JNI”
on page 67 for information on the -Xrunjnichk suboptions.
–memorycheck option
The -memorycheck option can help you identify memory leaks inside the JVM.
The -memorycheck option traces the JVM calls to the operating system’s malloc()
148 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Windows - debugging memory leaks
and free() functions, and identifies any JVM mistakes in memory allocation. See
Appendix F, “Command-line options,” on page 329 for more information.
When a Java application seems to be running slowly, you should check the various
JIT options and ensure that a suitable JIT compiler exists for the virtual machine
before you try anything else. Refer to Chapter 27, “JIT problem determination,” on
page 237.
Use the hprof tool, which can help find the CPU usage problems with
applications. Different CPU options can be used to identify the method or thread
that consumes more CPU time. Hprof does not calculate the count of CPU
utilization by internal methods, but flattens the hierarchy of the methods and adds
the counts to the method that is at a lower level in the stack trace. Refer to java
-Xrunhprof:help (in Chapter 32, “Using the JVMPI,” on page 297) for further
options.
Other tools, such as JProf, ProGuard, and JinSight, can give further inputs on
various parameters of a program running in Java.
v A heapdump (see Chapter 22, “Using Heapdump,” on page 205) if you think
that you have a memory consumption problem.
v Javadump snapshots (see Chapter 21, “Using Javadump,” on page 191) of the
JVM before performance became a problem and after.
v If performance is a permanent problem, send a couple of snapshots that are
separated by approximately 10 minutes, by using the dump extractor (see
“General debugging techniques” on page 145) after the point at which
performance became a problem.
150 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 17. z/OS problem determination
This chapter describes problem determination on z/OS in:
v “Setting up and checking your z/OS environment”
v “General debugging techniques” on page 152
v “Diagnosing crashes” on page 153
v “Debugging hangs” on page 160
v “Debugging memory leaks” on page 161
v “Debugging performance problems” on page 163
v “Collecting data from a fault condition in z/OS” on page 164
Maintenance
The Java for z/OS website at:
http://www-1.ibm.com/servers/eserver/zseries/software/java/
has up-to-date information about any changing operating system prerequisites for
correct JVM operation. In addition, any new prerequisites are described in PTF
HOLDDATA.
LE settings
Language Environment (LE) Runtime Options (RTOs) affect operation of C and
C++ programs such as the JVM. In general, the options that developers set by
using C #pragma statements in the code should not be overridden because they
are generated as a result of testing to provide the best operation of the JVM.
Environment variables
Environment variables that change the operation of the JVM in one release can be
deprecated or change meaning in a following release. Therefore, you should review
environment variables that are set for one release, to ensure that they still apply
after any upgrade.
This area is used for the allocation of the Java heap where instances of Java objects
are allocated and managed by Garbage Collection. The area is used also for any
underlying allocations that the JVM makes during operations. For example, the JIT
compiler obtains work areas for compilation of methods and to store compiled
code.
Because the JVM must preallocate the maximum Java heap size so that it is
contiguous, the total private area requirement is that of the maximum Java heap
size that is set by the -Xmx option (or the 64 MB default if this is not set), plus an
allowance for underlying allocations. A total private area of 140 MB is therefore a
reasonable requirement for an instance of a JVM that has the default maximum
heap size.
If the private area is restricted by either a system parameter or user exit, failures to
obtain private storage occur. These failures show as OutOfMemoryErrors or
Exceptions, failures to load dlls, or failures to complete subcomponent initialization
during startup.
Setting up dumps
The JVM, by default, generates a Javadump and System Transaction Dump
(SYSTDUMP) when any of the following occurs:
v A SIGQUIT signal is received
v The JVM aborts because of a fatal error
v An unexpected native exception occurs (for example, a SIGSEGV, SIGILL, or
SIGFPE signal is received)
You can use JAVA_DUMP_OPTS to change the dumps that are produced on the
various types of signal. You can use JAVA_DUMP_TDUMP_PATTERN to change
the naming convention to which the SYSTDUMP is written as an MVS dataset.
Both of these variables are described in Chapter 23, “JVM dump initiation,” on
page 209.
152 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
z/OS - general debugging techniques
Using dbx
The dbx utility has been improved for z/OS V1R6. You can use dbx to analyze
transaction dumps and to debug a running application. For information about dbx,
see the z/OS documentation (z/OS V1R6.0 Unix System Services Programming Tools).
Diagnosing crashes
A crash should occur only because of a fault in the JVM, or because of a fault in
native (JNI) code that is being run inside the Java process. A crash is more strictly
defined on z/OS as a program check that is handled by z/OS UNIX as a fatal
signal (for example, SIGSEGV for PIC4, 10 or 11 or SIGILL for PIC1).
Documents to gather
When one of these fatal signals occurs, the JVM Signal Handler takes control. The
default action of the signal handler is to request an unformatted transaction dump
through the BCP IEATDUMP service and to produce a formatted dump of internal
JVM state, which is known as the Javadump. Output should be written to the
message stream that is written to stderr in the form of:
Unhandled exception
Type=GPF vmState=0x00000000
Target=2_20_20040813_1849_BHdSMr (z/OS 06.00)
CPU=s390x (2 logical CPUs) (0x0 RAM)
signal=0000000b
gpr0=00000000000003e7 gpr1=0000000000000000 gpr2=0000000100006160 gpr3=0000000000000010
gpr4=00000001082fe780 gpr5=00000000000000c0 gpr6=0000000000000000 gpr7=00000000122c66e8
gpr8=0000000000000007 gpr9=00000000122c6708 gpr10=0000000108377e70 gpr11=000000010c83fb78
gpr12=0000000108300c60 gpr13=0000000108377e00 gpr14=000000007cd18938 gpr15=0000000000000000
fpr0=4841230c72000000 fpr1=4580000000000000 fpr2=4e80000117ddc374 fpr3=3ff0000000000000
fpr4=406f000000000000 fpr5=0000000000000000 fpr6=0000000000000000 fpr7=0000000000000000
fpr8=0000000000000000 fpr9=0000000000000000 fpr10=0000000000000000 fpr11=0000000000000000
fpr12=0000000000000000 fpr13=0000000000000000 fpr14=0000000000000000 fpr15=0000000000000000
psw0=0785240180000000 psw1=00000000122c66f8 fpc=0000000000000000
JVMDUMP0006I Processing Dump Event "gpf", detail "" - Please Wait.
JVMDUMP0007I JVM Requesting System Dump using ’CWHITE.JVM.TDUMP.CWHITE9.D040818.T085946’
IEATDUMP success for DSN=’CWHITE.JVM.TDUMP.CWHITE9.D040818.T085946’
CEEDUMP success for FILE=’/u/cwhite/work/Test/dumpTest/CEEDUMP.20040818.085947.67240533’
JVMDUMP0007I JVM Requesting CEE Dump using ’/u/cwhite/work/Test/dumpTest/CEEDUMP.20040818.090014.67240533’
CEEDUMP success for FILE=’/u/cwhite/work/Test/dumpTest/CEEDUMP.20040818.090014.67240533’
JVMDUMP0010I CEE Dump written to /u/cwhite/work/Test/dumpTest/CEEDUMP.20040818.090014.67240533
JVMDUMP0007I JVM Requesting Java Dump using ’/u/cwhite/work/Test/dumpTest/javacore.20040818.090040.67240533.txt’
JVMDUMP0010I Java Dump written to /u/cwhite/work/Test/dumpTest/javacore.20040818.090040.67240533.txt
JVMDUMP0013I Processed Dump Event "gpf", detail "".
The output shows the location in HFS into which the Javadump file was written
and the name of the MVS dataset to which the transaction dump is written. These
locations are configurable and are described in Chapter 20, “Overview of the
available diagnostics,” on page 187 and Chapter 23, “JVM dump initiation,” on
page 209.
These two documents (that is, the Javadump file and the transaction dump)
provide the ability to determine the failing function, and therefore decide which
product owns the failing code, be it the JVM, application JNI code, or third part
native libraries (for example native JDBC drivers).
The most practical way to find where the exception occurred is to review either the
CEEDUMP or the Javadump. Both of these show where the exception occurred and
the native stack trace for the failing thread. The same information can be obtained
from the transaction dump by using either IPCS LEDATA VERB Exit, or the
svcdump.jar toolset. These generate a report that is similar to the CEEDUMP.
In each case, the report shows the C-Stack (or native stack, which is separate from
the Java stack that is built by the JVM because one method gives control to
another). The C-stack frames are also known on z/OS as DSAs, because this is the
name of the control block that LE provides as a native stack frame for a C/C++
program. The following traceback from a CEEDUMP shows where a failure
occurred:
154 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
z/OS - diagnosing crashes
Traceback:
DSA Entry E Offset Load Mod Program Unit Service Status
00000001 __cdump +00000000 CELQLIB HLE7709 Call
00000002 @@WRAP@MULTHD
+00000266 CELQLIB Call
00000003 j9dump_create
+0000035C *PATHNAM j040813 Call
00000004 doSystemDump+0000008C *PATHNAM j040813 Call
00000005 triggerDumpAgents
+00000270 *PATHNAM j040813 Call
00000006 vmGPHandler +00000C4C *PATHNAM j040813 Call
00000007 gpHandler +000000D4 *PATHNAM j040813 Call
00000008 __zerro +00000BC4 CELQLIB HLE7709 Call
00000009 __zerros +0000016E CELQLIB HLE7709 Call
0000000A CEEHDSP +00003A2C CELQLIB CEEHDSP HLE7709 Call
0000000B CEEOSIGJ +00000956 CELQLIB CEEOSIGJ HLE7709 Call
0000000C CELQHROD +00000256 CELQLIB CELQHROD HLE7709 Call
0000000D CEEOSIGG -08B3FBBC CELQLIB CEEOSIGG HLE7709 Call
0000000E CELQHROD +00000256 CELQLIB CELQHROD HLE7709 Call
0000000F Java_dumpTest_runTest
+00000044 *PATHNAM Exception
00000010 RUNCALLINMETHOD
-0000F004 *PATHNAM Call
00000011 gpProtectedRunCallInMethod
+00000044 *PATHNAM j040813 Call
00000012 j9gp_protect+00000028 *PATHNAM j040813 Call
00000013 gpCheckCallin
+00000076 *PATHNAM j040813 Call
00000014 callStaticVoidMethod
+00000098 *PATHNAM j040813 Call
00000015 main +000029B2 *PATHNAM j904081 Call
00000016 CELQINIT +00001146 CELQLIB CELQINIT HLE7709 Call
Notes:
1. The stack frame that has a status value of Exception indicates where the crash
occurred. In this example, the crash occurs in the function
Java_dumpTest_runTest.
2. The value under Service for each DSA is the service string. The string is built in
the format of jyymmdd, where j is the identifier for the code owner and yymmdd
is the build date. A service string like this indicates that the function is part of
the JVM. Similarly, any program unit whose z/OS UNIX filename begins with
/u/sovbld is part of the JVM. All functions should have the same build date,
unless you have been supplied with a dll by IBM Service for diagnostic or
temporary fix purposes.
The normal way to inspect a TDUMP is by using IPCS (see “Using IPCS
commands” on page 152). You can also inspect a TDUMP using a Java application
such as svcdump, or jdmpview, if the dump data set has been transferred in binary
mode to the inspecting system.
A TDUMP can contain multiple Address Spaces. It is important to work with the
correct address space associated with the failing java process.
If you change the Source default, IPCS displays the current default address
space for the new source and ignores any data entered in the address space
field.
4. To initialize the dump, select one of the analysis functions, such as IPCS option
2.4 SUMMARY - Address spaces and tasks, which will display something like
the following and give the TCB address. (Note that non-zero CMP entries
reflect the termination code.)
TCB: 009EC1B0
CMP...... 940C4000 PKF...... 80 LMP...... FF DSP...... 8C
TSFLG.... 20 STAB..... 009FD420 NDSP..... 00002000
JSCB..... 009ECCB4 BITS..... 00000000 DAR...... 00
RTWA..... 7F8BEDF0 FBYT1.... 08
Task non-dispatchability flags from TCBFLGS5:
Secondary non-dispatchability indicator
Task non-dispatchability flags from TCBNDSP2:
SVC Dump is executing for another task
SVRB: 009FD9A8
WLIC..... 00000000 OPSW..... 070C0000 81035E40
LINK..... 009D1138
PRB: 009D1138
WLIC..... 00040011 OPSW..... 078D1400 B258B108
LINK..... 009ECBF8
EP....... DFSPCJB0 ENTPT.... 80008EF0
PRB: 009ECBF8
WLIC..... 00020006 OPSW..... 078D1000 800091D6
LINK..... 009ECC80
156 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
z/OS - diagnosing crashes
For suspected loops you might need to concentrate on ASID and exclude any
branch tracing:
ip systrace asid(x’3c’) exclude(br)
ip summ format asid(x’94’)
To find the list of TCBs, issue a find command for ″T C B″.
ip verbx ledata ’ceedump asid(94) tcb(009DFE88)
Obtains a traceback for the specified TCB.
ip omvsdata process detail asid(x’94’)
Shows a USS perspective for each thread.
ip verbx vsmdata ’summary noglobal’
Provides a summary of the local data area:
LOCAL STORAGE MAP
___________________________
| |80000000 <- Top of Ext. Private
| Extended |
| LSQA/SWA/229/230 |80000000 <- Max Ext. User Region Address
|___________________________|7F4AE000 <- ELSQA Bottom
| |
| (Free Extended Storage) |
|___________________________|127FE000 <- Ext. User Region Top
| |
| Extended User Region |
|___________________________|10D00000 <- Ext. User Region Start
: :
: Extended Global Storage :
=======================================<- 16M Line
: Global Storage :
:___________________________: A00000 <- Top of Private
| |
| LSQA/SWA/229/230 | A00000 <- Max User Region Address
Input Specifications:
158 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
z/OS - diagnosing crashes
blscddir dsname(’DUMPHLQ.ddir’)
Creates an IPCS DDIR.
runc addr(2657c9b8) link(20:23) chain(9999) le(x’1c’) or runc addr(25429108)
structure(tcb)
Runs a chain of control blocks using the RUNCHAIN command.
addr: the start address of the first block
link: the link pointer start and end bytes within the block (decimal)
chain: the maximum number of blocks to be searched (default=999)
le: the length of data from the start of each block to be displayed (hex)
structure: control block type
Debugging hangs
A hang refers to a process that is still present, but has become unresponsive. This
lack of response can be caused by any one of these reasons:
v The process has become deadlocked, so no work is being done. Usually, the
process is taking up no CPU time.
v The process has become caught in an infinite loop. Usually, the process is taking
up high CPU time.
v The process is running, but is suffering from very bad performance. This is not
an actual hang, but is normally initially thought to be one.
If the value of TIME increases in a few minutes, the process is still using CPU, and
is not deadlocked.
For an explanation of deadlocks and how the Javadump tool is used to diagnose
them, see “Locks, monitors, and deadlocks (LOCKS)” on page 193.
When the console dump has been generated, you can view the Systrace in IPCS to
identify threads that are looping. You can do this in IPCS as follows:
ip systrace asid(x’007d’) time(gmt)
160 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
z/OS - debugging hangs
This command formats out the system trace entries for all threads that are in
address space 0x7d. The time(gmt) option converts the TOD clock entries, which
are in the system trace, to a human readable form.
From the output produced, you can determine which are the looping threads by
identifying patterns of repeated CLCK and EXT1005 interrupt trace entries, and
subsequent redispatch DSP entries. You can identify the instruction address range
of the loop from the PSWs (Program Status Words) that are traced in these entries.
Allocations to LE HEAP
The Java process makes two distinct allocation types to the LE HEAP.
The first type is the allocation of the Java heap that garbage collection manages.
The Java heap is allocated during JVM startup as a contiguous area of memory. Its
size is that of the maximum Java heap size parameter. Even if the minimum,
initial, heap size is much smaller, you must allocate for the maximum heap size to
ensure that one contiguous area will be available should heap expansion occur.
The second type of allocation to the LE HEAP is that of calls to malloc() by the
JVM, or by any native JNI code that is running under that Java process. This
includes application JNI code, and third party native libraries; for example, JDBC
drivers.
The process address space on 31-bit z/OS has 31-bit addressing that allows the
addressing of 2 GB of virtual storage. The process address space on 64-bit z/OS
has 64-bit addressing that allows the addressing of over 2 GB of virtual storage.
This storage includes areas that are defined as common (addressable by code
running in all address spaces) and other areas that are private (addressable by
code running in that address space only).
The size of common areas is defined by several system parameters and the number
of load modules that are loaded into these common areas. On many typical
systems, the total private area available is about 1.4 GB. From this area, the Java
heap is allocated at startup, along with any subsequent calls to malloc(). A leak of
Java objects, therefore, does not cause VSM to issue an abend878 rc10 because of
lack of private storage. This abend can be caused only by unbounded growth of
storage that is allocated through malloc() for underlying JVM resources requested
by JVM components such as AWT or the JIT, or by calls to malloc() from
application JNI code and third party native libraries.
If you change the LE HEAP setting, you are asking LE to GETMAIN different
amounts of initial or incremental storage for use by all C applications. This has no
effect on a Java application throwing an OutOfMemoryError. If errors are received
because of lack of private storage, you must ensure that the region size is big
enough to allocate for the Java heap and for the underlying JVM resources. Note
that for TSO/E address spaces, the REGION size for USS processes that are like
the JVM inherit from the TSO/E address space, whereas in the case of rlogin or
telnet sessions, the region size is determined by the BPXPRMxx parameter
MAXASSIZE.
OutOfMemoryErrors
The JVM throws a java.lang.OutOfMemoryError (OOM) when the heap is full, and
it cannot find space for object creation. Heap usage is a result of the application
design, its use and creation of object populations, and the interaction between the
heap and the garbage collector.
The operation of the JVM’s Garbage Collector is such that objects are continuously
allocated on the heap by mutator (application) threads until an object allocation
fails. At this point, a garbage collection cycle begins. At the end of the cycle, the
allocation is retried. If successful, the mutator threads resume where they stopped.
If the allocation request cannot be fulfilled, an OutOfMemory exception is thrown.
The Garbage Collector uses a mark and sweep algorithm. That is, the Garbage
Collector marks every object that is referenced from the stack of a thread, and
every object that is referenced from a marked object. Any object on the heap that
remains unmarked is cleared up during the sweep phase because it is no longer
live.
An OutOfMemory exception occurs when the live object population requires more
space than is available in the Java managed heap. It is possible that this can occur
not because of an object leak, but because the Java heap is not large enough for the
application that is being run. In this case, you can use the -Xmx option on the JVM
invocation to increase the heap size and remove the problem, as follows:
java -Xmx320m MyApplication
If the failure is occurring under javac, remember that the compiler is a Java
program itself. To pass parameters to the JVM that is created for the compile, use
the -J option to pass the parameters that you would normally pass directly. For
example, the following passes a 128 MB maximum heap to javac:
javac -J-Xmx128m MyApplication.java
In the case of a genuine object leak, the increased heap size does not solve the
problem, but increases the time for a failure to occur.
162 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
z/OS - debugging memory leaks
OutOfMemory errors are also generated when a JVM call to malloc() fails. This
should normally have an associated error code.
The -verbosegc (-verbose:gc) switch causes the JVM to print out messages when a
garbage collection cycle begins and ends. These messages indicate how much live
data remains on the heap at the end of a collection cycle. In the case of a Java
object leak, the amount of free space on the heap after a garbage collection cycle
will be seen to decrease over time. See “Basic diagnostics (-verbosegc)” on page
242.
These actions are listed in order of severity. As the number increases, the Garbage
Collector is becoming more desperate for memory. A high action number is a good
indication of a significant shortage of Java heap space.
A Java object leak is caused when an application retains references to objects that
are no longer in use. In a C application, a developer in required to free memory
when it is no longer required. A Java developer is required to removed references
to objects that are no longer required. The developer normally does this by setting
references to null. When this does not happen, the object, and anything that that
object references in turn, continues to reside on the Java heap and cannot be
removed. This typically occurs when data collections are not managed correctly;
that is, the mechanism to remove objects from the collection is either not used, or
used incorrectly.
Check whether the system is tuned to cope with the Java managed heap size that
you have specified. If the Java managed heap size is large, on a system without
large amounts of real storage you might see a performance degradation caused by
excessive paging.
If the system intermittently sees high CPU usage for the process in which Java is
running, this might be a symptom of excessive garbage collection pauses. The
garbage collector is a ″Stop The World″ type, and collection cycles are normally so
short (from 5-500 milliseconds, for example) that they are not observed externally.
If the collection cycle takes longer for some reason, or occurs more frequently than
expected, this will be observed as high CPU. This is because the garbage collection
code is CPU-intensive, and the collector uses helper threads for marking objects.
These helper threads could possibly be running on all available CPUs. In addition,
some mutator threads might be in short ″busy waits″ for the cycle to end. In this
case, turn on switch -verbose:gc to see how often the cycles are occurring and
what their duration is. Pause times over several seconds are worth further
investigation. You should also use switch -Xgcpolicy:optavgpause to activate JVM
use of concurrent marking, to reduce and smooth out pause times, at some small
reduction in overall throughput. If this does not help resolve the problem, contact
IBM Service before gathering more information.
The JVM on z/OS makes use of the IEATDUMP service to capture unformatted
dumps. These dumps can then be processed with IPCS on z/OS. The internal high
performance trace allows for the creation of binary trace files, which can be
post-processed on any platform that supports Java.
164 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 18. Debugging the ORB
One of the first tasks that you must do when debugging an ORB problem is to
determine whether the problem is in the client-side or in the server-side of the
distributed application. Think of a typical RMI-IIOP session as a simple,
synchronous communication between a client that is requesting access to an object,
and a server that is providing it. During this communication, a problem might
occur in the execution of one of the following steps:
1. The client writes and sends a request to the server.
2. The server receives and reads the request.
3. The server execute the task in the request.
4. The server writes and sends a reply back.
5. The client receives and reads the reply.
It is not always easy to identify where the problem occurred. Often, the
information that the application returns, in the form of stack traces or error
messages, is not enough for you to make a decision. Also, because the client and
server communicate through their ORBs, it is likely that if a problem occurs, both
sides will record an exception or unusual behavior.
This chapter describes all the clues that you can use to find the source of the ORB
problem. It also describes a few common problems that occur more frequently. The
topics are:
v “Identifying an ORB problem”
v “Debug properties” on page 167
v “ORB exceptions” on page 168
v “Interpreting the stack trace” on page 170
v “Interpreting ORB traces” on page 171
v “Common problems” on page 174
v “IBM ORB service: collecting data” on page 176
Platform-dependent problem
If possible, run the test case on more than one platform. All the ORB code is
shared. You can nearly always reproduce genuine ORB problems on any platform.
If you have a platform-specific problem, it is likely to be in some other component.
JIT problem
JIT bugs are very difficult to find. They might show themselves as ORB problems.
When you are debugging or testing an ORB application, it is always safer to switch
off the JIT by setting the option -Xint.
Fragmentation
Disable fragmentation when you are debugging the ORB. Although fragmentation
does not add complications to the ORB’s functioning, a fragmentation bug can be
difficult to detect because it will most likely show as a general marshalling
problem. The way to disable fragmentation is to set the ORB property
com.ibm.CORBA.FragmentSize=0. You must do this on the client side and on the
server side.
Packaging
Table 7. Packaging
IBM Platforms Non-IBM Platform
Runtime classes jre/lib/ibmorb.jar jre/lib/endorsed/ibmorb.jar
Tools classes lib/tools.jar lib/ibmtools.jar
CORBA API classes jre/lib/ibmorbapijar jre/lib/endorsed/ibmorbapijar
Runtime support None jre/lib/endorsed/ibmext.jar
rmic wrapper None ibm_bin/rmic
ibm_bin/rmic.bat
idlj wrapper None ibm_bin/idlj
ibm_bin/idlj.bat
ORB versions
The ORB component carries a few version properties that you can display by
invoking the main method of the following classes:
1. com.ibm.CORBA.iiop.Version (ORB runtime version)
2. com.ibm.tools.rmic.iiop.Version (for tools; for example, idlj and rmic)
3. rmic -iiop -version (run the command-line for rmic)
Note: Items 2 and 3 are alternative methods for reaching the same class.
166 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
ORB - debug properties
Debug properties
Attention: Do not turn on tracing for normal operation, because it might cause
performance degradation. Even if you have switched off tracing, FFDC (First
Failure Data Capture) is still working, so that only serious errors are reported. If a
debug output file is generated, examine it to check on the problem. For example,
the server might have stopped without performing an ORB.shutdown().
You can use the following properties to enable the ORB traces:
v com.ibm.CORBA.Debug: This property turns on trace, message, or both. If you
set this property to trace only traces are turned on; if you set it to message, only
messages are turned on. Any other value, or no value, turns on traces and
messages. The only way not to set this property is not to specify it. A value of
false enables it anyway. When enabling any kind of tracing, it is safe to turn this
property on.
v com.ibm.CORBA.Debug.Output: This property redirects traces to a file, which
is known as a trace log. When this property is not specified, or it is set to an
empty field, the file name defaults to the format
orbtrc.DDMMYYYY.HHmm.SS.txt, where D=Day; M=Month; Y=Year; H=Hour
(24 hour format); m=Minutes; S=Seconds. Note that if the application (or Applet)
does not have the privilege that it requires to write to a file, the trace entries go
to stderr.
v com.ibm.CORBA.CommTrace: This property turns on wire tracing. Every
incoming and outgoing GIOP message will be output to the trace log. You can
set this property independently from Debug; this is useful if you want to look
only at the flow of information, and you are not too worried about debugging
the internals. The only two values that this property can have are true and false.
The default is false.
For rmic -iiop or rmic -idl, the following diagnostic tools are available:
v -J-Djavac.dump.stack=1: This tool ensures that all exceptions are caught.
v -Xtrace: This tool traces the progress of the parse step.
If you are working with an IBM SDK, you can obtain CommTrace for the transient
name server (tnameserv) by using the standard environment variable
IBM_JAVA_OPTIONS. In a separate command session to the server or client
SDKs, you can use:
set IBM_JAVA_OPTIONS=-Dcom.ibm.CORBA.CommTrace=true -Dcom.ibm.CORBA.Debug=true
The setting of this environment variable affects each Java process that is started, so
use this variable carefully. Alternatively, you can use the -J option to pass the
properties through the tnameserv wrapper, as follows:
tnameserv -J-Dcom.ibm.CORBA.Debug=true
ORB exceptions
You are using this chapter because you think that your problem is related to the
ORB. Unless your application is doing nothing or giving you the wrong result, it is
likely that your log file or terminal is full of exceptions that include the words
“CORBA” and “rmi” many times. All unusual behavior that occurs in a good
application is highlighted by an exception. This principle is also true for the ORB
with its CORBA exceptions. Similarly to Java, CORBA divides its exceptions into
user exceptions and system exceptions.
User exceptions
User exceptions are IDL defined and inherit from org.omg.CORBA.UserException.
These exceptions are mapped to checked exceptions in Java; that is, if a remote
method raises one of them, the application that invoked that method must catch
the exception. User exceptions are usually not fatal exceptions and should always
be handled by the application. Therefore, if you get one of these user exceptions,
you know where the problem is, because the application developer had to make
allowance for such an exception to occur. In most of these cases, the ORB is not the
source of the problem.
System exceptions
System exceptions are thrown transparently to the application and represent an
unusual condition in which the ORB cannot recover gracefully, such as when a
connection is dropped. The CORBA 2.6 specification defines 31 system exceptions
and their mapping to Java. They all belong to the org.omg.CORBA package. The
CORBA specification defines the meaning of these exceptions and describes the
conditions in which they are thrown.
168 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
ORB exceptions
Usually the completion status is not very useful. However, the minor code can be
essential when the stack trace is missing. In many cases, the minor code identifies
the exact location of the ORB code where the exception is thrown (see the section
below) and can be used by the vendor’s service team to localize the problem
quickly. However, for standard CORBA minor codes, this is not always possible.
For example:
org.omg.CORBA.OBJECT_NOT_EXIST: SERVANT_NOT_FOUND minor code: 4942FC11 completed: No
Minor codes are usually expressed in hexadecimal notation (except for SUN’s
minor codes, which are in decimal notation) that represents four bytes. The OMG
organization has assigned to each vendor a range of 4096 minor codes. The IBM
vendor-specific minor code range is 0x4942F000 through 0x4942FFFF. Appendix D,
“CORBA minor codes,” on page 321 gives diagnostic information for the
most-common minor codes.
System exceptions might also contain a string that describes the exception and
other useful information. You will see this string when you interpret the stack
trace.
The ORB tends to map all Java exceptions to CORBA exceptions. A runtime
exception is mapped to a CORBA system exception, while a checked exception is
mapped to a CORBA user exception.
More exceptions other than the CORBA exceptions could be generated by the ORB
component in a code bug. All the Java unchecked exceptions and errors and others
that are related to the ORB tools rmic and idlj must be considered. In this case, the
only way to determine whether the problem is in the ORB, is to look at the
generated stack trace and see whether the objects involved belong to ORB
packages.
If your program uses any of these methods, ensure that it is granted the necessary
permissions.
The following example describes a stack trace that was generated by a server ORB
running in the WebSphere Application Server:
Description string
The example stack trace shows that the application has caught a CORBA
org.omg.CORBA.MARSHAL system exception. After the MARSHAL exception,
some extra information is provided in the form of a string. This string should
specify minor code, completion status, and other information that is related to the
problem. Because CORBA system exceptions are alarm bells for an unusual
condition, they also hide inside what the real exception was.
Usually, the type of the exception is written in the message string of the CORBA
exception. The trace shows that the application was reading a value (read_value())
when an IllegalAccessException occurred that was associated to class
com.ibm.ws.pmi.server.DataDescriptor. This is a hint of the real problem and
should be investigated first.
170 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
ORB - interpreting the stack trace
Nested exceptions
In the example, the ORB mapped a Java exception to a CORBA exception. This
exception is sent back to the client later as part of a reply message. The client ORB
reads this exception from the reply. It maps it to a Java exception
(java.rmi.RemoteException according to the CORBA specification) and throws this
new exception back to the client application.
Along this chain of events, often the original exception becomes hidden or lost, as
does its stack trace. On early versions of the ORB (for example, 1.2.x, 1.3.0) the
only way to get the original exception stack trace was to set some ORB debugging
properties. Newer versions have built-in mechanisms by which all the nested stack
traces are either recorded or copied around in a message string. When dealing with
an old ORB release (1.3.0 and earlier), it is a good idea to test the problem on
newer versions. Either the problem is not reproducible (known bug already solved)
or the debugging information that you obtain is much more useful.
Message trace
Here is a simple example of a message:
16:02:33.978 com.ibm.rmi.util.Version logVersions:88 P=953197:O=0:CT ORBRas[default] IBM Java ORB build cndev-20030114
This message records the time, the package, and the method name that was
invoked. In this case, logVersions() prints out to the log file, the version of the
running ORB.
After the first colon in the example message, the line number in the source code
where that method invocation is done is written (88 in this case). Next follows the
letter P that is associated with the process number that was running at that
moment. This number is related (by a hash) to the time at which the ORB class
was loaded in that process. It unlikely that two different processes load their ORBs
at the same time.
The following O=0 (alphabetic O = numeric 0) indicates that the current instance of
the ORB is the first one (number 0). CT specifies that this is the main (control)
thread. Other values are: LT for listener thread, RT for reader thread, and WT for
worker thread.
The ORBRas field shows which RAS implementation the ORB is running. It is
possible that when the ORB runs inside another application (such as a WebSphere
application), the ORB RAS default code is replaced by an external implementation.
The remaining information is specific to the method that has been logged while
executing. In this case, the method is a utility method that logs the version of the
ORB.
This example of a possible message shows the logging of entry or exit point of
methods, such as:
In this case, the constructor (that is, <init>) of the class Connection is invoked. The
tracing records when it started and when it finished. For operations that include
the java.net package, the ORBRas logger prints also the number of the local port
that was involved.
Comm traces
Here is an example of comm (wire) tracing:
// Summary of the message containing name-value pairs for the principal fields
OUT GOING:
Request Message // It is an out going request, therefore we are dealing with a client
Date: 31 January 2003 16:17:34 GMT
Thread Info: P=852270:O=0:CT
Local Port: 4899 (0x1323)
Local IP: 9.20.178.136
Remote Port: 4893 (0x131D)
Remote IP: 9.20.178.136
GIOP Version: 1.2
Byte order: big endian
Context ID: 1229081874 (0x49424D12) // Partner version service context. IBM only
Context data: length = 8 (0x8)
00000000 14000005
172 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
interpreting ORB traces
Note: The italic comments that start with a double slash have been added for
clarity; they are not part of the traces.
In this example trace, you can see a summary of the principal fields that are
contained in the message, followed by the message itself as it goes in the wire. In
the summary are several field name-value pairs. Each number is in hexadecimal
notation.
Appendix C, “CORBA GIOP message format,” on page 317 gives details of the
structure of a GIOP message. See also CORBA specification chapters 13 and 15.)
Client or server
From the first line of the summary of the message, you can identify whether the
host to which this trace belongs is acting as a server or as a client. OUT GOING
means that the message has been generated in the machine where the trace was
taken and is sent to the wire.
The trace shows that the message is an outgoing request. Therefore, this trace is a
client trace, or at least part of the trace where the application acts as a client.
Time information and host names are reported in the header of the message.
The Request ID and the Operation (“message” in this case) fields can be very
helpful when multiple threads and clients destroy the logical sequence of the
traces.
The GIOP version field can be checked if different ORBs are deployed. If two
different ORBs support different versions of GIOP, the ORB that is using the more
recent version of GIOP should fall back to a common level. By checking that field,
however, you can easily check whether the two ORBs speak the same language.
Service contexts
The header also records three service contexts, each consisting of a context ID and
context data. A service context is extra information that is attached to the message
for purposes that can be vendor-specific (such as the IBM Partner version that is
described in the IOR in Chapter 5, “Understanding the ORB,” on page 33).
Some CORBA-defined service contexts are available. One of these is the Codeset.
In the example, the codeset context has ID 1 and data 00000000 00010001
00010100. Bytes 5 through 8 specify that characters that are used in the message are
encoded in ASCII (00010001 is the code for ASCII). Bytes 9 through 12 instead are
related to wide characters.
The other CORBA service context, which is present in the example, is the Codebase
service context. It stores information about how to call back to the client to access
resources in the client such as stubs, and class implementations of parameter
objects that are serialized with the request.
Common problems
This section describes some of the problems that you might find.
A simple test that you can do is to keep only one CPU running and see whether
the problem disappears. If it does, you know that you must have a synchronization
problem in the application.
Also, you must understand what the application is doing while it hangs. Is it
waiting (low CPU usage), or it is looping forever (almost 100% CPU usage)? Most
of the cases are a waiting problem.
An example of a standby condition is where the client sends a request to the server
and stops while waiting for the reply. The default behavior of the ORB is to wait
indefinitely.
174 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
ORB application hangs
Also, set the RequestTimeout to a value other than 0. Because a reply to a request
is often large, allow more time; for example, 10000 milliseconds. These values are
suggestions and might be too low for slow connections. When a request times out,
the client receives an explanatory CORBA exception.
In general, stop the application, enable the orb traces (see previous section) and
restart the application. When the hang is reproduced, the partial traces that can be
retrieved can be used by the IBM ORB service team to help understand where the
problem is.
Running the client without the server running before the client
is invoked
This operation outputs:
(org.omg.CORBA.COMM_FAILURE)
Hello Client exception:
org.omg.CORBA.COMM_FAILURE:minor code:1 completed:No
at com.ibm.rmi.iiop.ConnectionTable.get(ConnectionTable.java:145)
at com.ibm.rmi.iiop.ConnectionTable.get(ConnectionTable.java:77)
at com.ibm.rmi.iiop.GIOPImpl.createRequest(GIOPImpl.java:98)
at com.ibm.rmi.iiop.GIOPImpl.createRequest(GIOPImpl.java:75)
at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:440)
at com.ibm.rmi.corba.ClientDelegate.is_a(ClientDelegate.java:571)
at org.omg.CORBA.portable.ObjectImpl._is_a(ObjectImpl.java:74)
at org.omg.CosNaming.NamingContextHelper.narrow(NamingContextHelper.java:58)
com.sun.jndi.cosnaming.CNCtx.callResolve(CNCtx.java:327)
at com.ibm.rmi.corba.InitialNamingClient.cachedInitialReferences(InitialNamingClient.j
at com.ibm.rmi.corba.InitialNamingClient.resolve_initial_references(InitialNamingClien
at com.ibm.rmi.corba.ORB.resolve_initial_references(ORB.java:1269)
.........
You must start the Java IDL name server before an application or applet starts that
uses its naming service. Installation of the Java IDL product creates a script
(Solaris: tnameserv) or executable file (Windows NT: tnameserv.exe) that starts the
Java IDL name server.
Start the name server so that it runs in the background. If you do not specify
otherwise, the name server listens on port 2809 for the bootstrap protocol that is
used to implement the ORB resolve_initial_references() and list_initial_references()
methods.
Clients of the name server must be made aware of the new port number. Do this
by setting the org.omg.CORBA.ORBInitialPort property to the new port number
when you create the ORB object.
Preliminary tests
The ORB is affected by problems with the underlying network, hardware, and
JVM. When a problem occurs, the ORB can throw an org.omg.CORBA.* exception,
some text that describes the reason, a minor code, and a completion status. Before
you assume that the ORB is the cause of problem, ensure the following:
v The scenario can be reproduced (not only on customers’ machines, but on a
similar setup configuration).
176 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
IBM ORB service: collecting data
v The JIT is disabled (see Chapter 27, “JIT problem determination,” on page 237).
Also:
1. Disable additional CPUs.
2. Eliminate memory dependencies with the client or server. The lack of physical
memory can be the cause of slow performance, apparent hangs, or crashes. To
remove these problems, ensure that you have a reasonable headroom of
memory. Remember that even with 1 GB of physical RAM, Java can use only
512 MB independently of what -Xmx is set to.
3. Check physical network problems (firewalls, com links, routers, DNS name
servers, and so on). These are the major causes of CORBA COMM_FAILURE
exceptions. As a test, ping your own machine name.
4. If the application is using a database such as DB2, switch to the most reliable
driver. For example, to isolate DB2 AppDriver, switch to Net Driver, which is
slower and uses sockets, but is more reliable.
Data to be collected
If after all these verifications, the problem is still present, collect at all nodes of the
problem the following:
v Operating system name and version.
v Output of java -version.
v Output of java com.ibm.CORBA.iiop.Version.
v Output of rmic -iiop -version, if rmic is involved.
v ASV build number (WebSphere Application Server only).
v If you think that the problem is a regression, include the version information for
the most recent known working build and for the failing build.
v If this is a runtime problem, collect debug and communication traces of the
failure from each node in the system (as explained earlier in this chapter).
v If the problem is in rmic -iiop or rmic -idl, set the options:
-J-Djavac.dump.stack=1 -Xtrace, and capture the output.
v Normally this step is not necessary. If it looks like the problem is in the buffer
fragmentation code, IBM service will return the defect asking for an additional
set of traces, which you can produce by executing with
-Dcom.ibm.CORBA.FragmentSize=0.
178 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 19. NLS problem determination
The JVM contains built-in support for different locales. This chapter provides an
overview of locales, with the main focus on fonts and font management.
v “Overview of fonts”
v “The font.properties file” on page 180
v “Font utilities” on page 181
v “Common problems and possible causes” on page 182
Overview of fonts
When you want to display text, either in SDK components (AWT or Swing), on the
console or in any application, characters have to be mapped to glyphs. A glyph is
an artistic representation of the character, in some typographical style, and is
stored in the form of outlines or bitmaps. Glyphs might not correspond
one-for-one with characters. For instance, an entire character sequence can be
represented as a single glyph. Also a single character may be represented by more
than one glyph (for example, in Indic scripts).
The most commonly available font types are TrueType and OpenType fonts.
application to use, type the command: xset -q "". If your PATH also points
to the SDK (as it should be), xset -q output also shows the fonts that are
bundled with the Developer Kit.
Use xset +fp and xset -fp to add and remove the font path respectively.
On Windows platforms
Most text processing applications have a drop-down list of the available system
fonts, or you can use the Settings->Control Panel->Fonts application.
On Linux and USS platforms, a typical font.properties entry looks like this:
serif.3=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-p-*-ibm-udcjp
where:
General font name is the font name that Java understands.
Style can be normal, italic, bold, bolditalic, and so on. The default is ″normal″.
Index specifies the sequence of searching for matching font glyphs, with zero
the highest priority.
Platform font name is the name of the font in the system.
If the JVM cannot load any fonts from the system, the characters are displayed
as small squares.
Font CharSet
These entries control the converter to be used to convert unicode strings.
fontcharset.serif.0=sun.iof.CharToByteISO8859_1
This indicates that to draw the font that is specified by serif.0, the
sun.iof.CharToByteISO8859_1 converter is used.
180 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
NLS - font.properties file
Alias
This is used to map one Java font to another.
alias.timesnewroman=serif
The font definitions for serif are used for the font timesnewroman.
Fontset
The fontset entry is used to match fonts specifically for TextArea and TextField
objects.
fontset.serif.plain=\
-jdk-lucidabright-medium-r-normal--*-%d-75-75-p-*-iso8859-1,\
-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0,\
-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0,\
-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-p-*-ibm-udcjp
Note: The Windows font.properties file refers to Arial Unicode MS. The Arial
Unicode MS font is part of Office 2000 and above. You can download it from
Microsoft if you have a license for Microsoft Office or related products.
Font utilities
setlocale(LC_ALL, "");
toplevel = XtAppInitialize(&context, "", NULL, 0, &argc, argv,
NULL, NULL, 0);
n=0;
XtSetArg(args[n], XmNgeometry, "=225x225+50+50"); n++;
XtSetArg(args[n], XmNallowShellResize, True); n++;
XtSetValues(toplevel, args, n);
xmstr =XmStringCreateLocalized(ptr);
n=0;
XtSetArg(args[n], XmNlabelString, xmstr); n++;
pushb = XmCreatePushButton(toplevel, "PushB", args, n);
XtManageChild(pushb);
182 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
NLS - common problems and possible causes
XtRealizeWidget(toplevel);
XtAppMainLoop(context);
}
Compilation: cc -lXm -lXt -o motif motif.c
Note that the Motif library is statically linked into the Linux JVMs, so it is not
possible to use this technique there.
184 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Part 4. Using diagnostic tools
This part of the book describes how to use the diagnostic tools that are available.
The chapters are:
v Chapter 20, “Overview of the available diagnostics,” on page 187
v Chapter 21, “Using Javadump,” on page 191
v Chapter 22, “Using Heapdump,” on page 205
v Chapter 23, “JVM dump initiation,” on page 209
v Chapter 24, “Using dump agents,” on page 213
v Chapter 25, “Using method trace,” on page 219
v Chapter 26, “Using the dump formatter,” on page 223
v Chapter 27, “JIT problem determination,” on page 237
v Chapter 28, “Garbage Collector diagnostics,” on page 241
v Chapter 29, “Class-loader diagnostics,” on page 257
v Chapter 30, “Tracing Java applications and the JVM,” on page 259
v Chapter 31, “Using the Reliability, Availability, and Serviceability Interface,” on
page 283
v Chapter 32, “Using the JVMPI,” on page 297
Note: JVMMI is not supported on the v1.4.2 platforms described in this book.
This book addresses the IBM Virtual Machine for Java. The diagnostics in this book
are all JVM diagnostics.
You need different tools to solve problems in each category. Most of the tools
described in this book are from IBM, either built into the JVM or as external
monitoring tools.
Platforms
IBM provides and supports Java on a number of platforms. These platforms can be
divided into the groups:
1. Linux
2. Windows
3. z/OS (previously called S/390)
The platform architectures are very different. You will find that:
v Some tools exist only for a given platform.
v Some tools have different versions for different platforms.
v Some tools are cross-platform.
The code that creates Javadumps is part of the JVM. You can control it by using
environment variables and runtime switches. By default, a Javadump is produced
when the JVM terminates unexpectedly (crashes) because of an operating system
signal or when the user enters a reserved key-combination (for example, Ctrl-Break
on Windows). A Javadump is a text file that summarizes the state of the JVM at
the instant the signal occurred.
Much of the content of the Javadump is IBM-specific; that is, it is present only in
the IBM Virtual Machine for Java. See Chapter 21, “Using Javadump,” on page 191
for details. Javadump is an automatic tool.
Heapdump
The IBM Virtual Machine for Java can generate a Heapdump, which is a record of
all the Java objects in the Java heap. Heapdump can generate Heapdump files at
the request of the user, in an out-of-memory condition, or when the JVM
terminates unexpectedly (a crash). Each Heapdump file contains details of every
object in the heap at the time it was generated. This is useful for diagnosing
several kinds of problems, in particular, memory-related problems.
Heapdump is IBM-specific; that is, it is present only in the IBM Virtual Machine
for Java. See Chapter 22, “Using Heapdump,” on page 205 for details.
The formatter understands the JVM and can be used to analyze its internals. Thus,
it is a useful tool to debug JVM crashes. You must have a basic knowledge of the
JVM internals to use this tool. The formatter is really for use on postmortem
dumps. However, it is also useful for checking if leak problems occur in JVM
resources.
For more information, see Chapter 26, “Using the dump formatter,” on page 223.
JVMPI tools
JVMPI is officially described by Sun as “an experimental interface for profiling”. It
is not yet a standard profiling interface. It is provided for the benefit of tools
vendors who have an immediate need for profiling hooks in the Java virtual
machine. Sun states that the JVMPI will continue to evolve, based on feedback
from customers and tools vendors. IBM fully supports the current JVMPI
188 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
diagnostics - cross-platform tools
specification and is fully compatible with the current Sun release of the technology.
Visit Sun’s website (java.sun.com/j2se/1.3/docs/guide/jvmpi) for more
information.
JVMPI tools conform to the JVM Profiling Interface that is common across all
JVMs. The IBM Virtual Machine for Java is fully JVMPI compatible. Any tool
conforming to JVMPI can be used to profile the IBM Virtual Machine for Java.
JVMPI tools help with problems involving leaks and performance, although profile
logs might give useful hints to the state of the JVM just before a crash or hang
problem.
The JVMPI is intended for interested parties to write profilers, but IBM provides a
useful agent with the IBM SDK.
For more information, see Chapter 32, “Using the JVMPI,” on page 297.
JPDA Tools
Java Platform Debugging Architecture (JPDA) is a common standard for debugging
JVMs. The IBM Virtual Machine for Java is fully JPDA compatible.
Any JPDA debugger can be attached to the IBM Virtual Machine for Java. Being
debuggers, these tools are best suited to tracing leaks or the conditions prior to a
crash or hang, if these are repeatable.
An example of such a tool is the debugger that is bundled with Eclipse for Java.
JVM trace
JVM trace is a key diagnostic tool for the JVM.
The IBM Virtual Machine for Java contains a large amount of embedded trace.
Naturally, this tracing is switched off by default. Command-line options allow you
to turn trace on, set exactly what is to be traced, and specify where the trace
output is to go.
Trace applies to performance and leak problem determination, although the trace
file might provide clues to the state of a JVM before a crash or hang.
Trace is an IBM-specific tool; that is, it is present only in the IBM Virtual Machine
for Java. See Chapter 30, “Tracing Java applications and the JVM,” on page 259 for
details. You need some considerable effort to master trace. However, it is an
extremely effective tool.
JVMRI
The JVMRI (JVM RAS Interface, where RAS stands for Reliability, Availability,
Serviceability). JVMRI allows you to control several JVM operations
programmatically.
For example, the IBM Virtual Machine for Java contains a large amount of
embedded trace. Tracing is switched off by default. A JVMRI agent acts as a
plug-in to allow real-time control of trace information. You use the -Xrun
command-line option so that the agent is loaded by the JVM itself at startup time.
When loaded, a JVMRI agent can dynamically switch JVM trace on and off, control
the trace level, and capture the trace output. The JVMRI applies to performance
and leak problem determination, although the trace file might provide clues to the
state of a JVM before a crash or hang.
The RAS plug-in interface is an IBM-specific interface; that is, it is present only in
the IBM Virtual Machine for Java. See Chapter 31, “Using the Reliability,
Availability, and Serviceability Interface,” on page 283 for details. You need some
programming skills and tools to be able to use this interface.
Application trace
Application trace allows you to place tracepoints in Java code to provide trace data
that is combined with other forms of trace. You can control the tracepoints at
start-up or enable them dynamically. For more information, see Chapter 30,
“Tracing Java applications and the JVM,” on page 259.
Application trace is an IBM-specific tool; that is, it is present only in the IBM
Virtual Machine for Java. See Chapter 30, “Tracing Java applications and the JVM,”
on page 259 for details. You need some considerable effort to master trace.
However, it is an extremely effective tool.
Method trace
Method trace permits the tracing of Java methods using the existing JVM trace
facility. The trace has entry, exit, and, optionally, input parameters. You can select
classes and methods for trace using wildcards. You start method trace by
command-line options at JVM startup time, or by using a JVMRI agent.
Method trace is an IBM-specific tool; that is, it is present only in the IBM Virtual
Machine for Java. See Chapter 25, “Using method trace,” on page 219 for details.
Basic method trace is simple to use, and very effective.
The variables are separately described for the tools and diagnostics to which they
apply, and are also all gathered together for reference in Appendix E,
“Environment variables,” on page 323
Platform tools
Platform-specific tools are documented in the appropriate sections that follow. All
platforms (except z/OS) have a dump extractor tool that feeds the cross-platform
dump formatter. For the other tools, each platform has a different toolset. Some
tools have versions for two or more platforms.
The Java service team has a prototype Java application that displays and analyses
the Java environment variables. If you want more details about this prototype,
send an e-mail to [email protected].
190 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 21. Using Javadump
Javadump produces files that contain diagnostic information related to the JVM
and a Java application captured at a point during execution. For example, the
information can be about the operating system, the application environment,
threads, stacks, locks, and memory. The exact contents depend on the platform on
which you are running. The files produced by Javadump are called ″Javadump
files″. By default, a Javadump occurs when the JVM terminates unexpectedly. A
Javadump can also be triggered by sending specific signals to the JVM.
Note: Javadump is also known as Javacore. This is NOT the same as a core file
(that is an operating system feature that can be produced by any program,
not just the JVM).
Note: “Interpreting a Javadump” on page 192 is the main part of this chapter.
Enabling a Javadump
Javadumps are enabled by default. To turn them off, set the environment variable
DISABLE_JAVADUMP to TRUE.
You can use the JAVA_DUMP_OPTS environment variable to control exactly when
a Javadump is produced; see Chapter 23, “JVM dump initiation,” on page 209 for
more information. You can also use the -Xdump agent option to get more
fine-grained control over Javadumps; see Chapter 24, “Using dump agents,” on
page 213 for more information.
Triggering a Javadump
The Javadump is generated when one of the following occurs:
v A fatal native exception occurs in the JVM (not a Java Exception).
v The JVM has completely run out of heapspace.
The exact conditions in which you get a Javadump vary depending on the
JAVA_DUMP_OPTS environment variable. For example, you can optionally get a
Javadump when the JVM terminates normally (on an interrupt). See Chapter 23,
“JVM dump initiation,” on page 209 for more information.
A ″fatal″ exception is one that causes the JVM to terminate. The JVM handles this
by producing a System dump followed by a Javadump and then terminates the
process. The behavior of the JVM in a failure is not affected by the Javadump and
should not affect the production of core files. However, it is possible that the
processing that is done to generate a Javadump might itself find a problem. In this
unlikely event, switch off Javadumps with the DISABLE_JAVADUMP=TRUE
environment variable.
Note: The exact format and content might be different from what is documented
at this stage.
In the user-controlled cases (the latter two), the JVM stops execution, performs the
dump, and then continues execution.
The signal for Linux is SIGQUIT. Use the command kill -3 n to send the signal to
a process with process id (PID) n. Alternatively, press Ctrl+\ in the shell window
that started Java.
You can get a Javadump in a ″totally out of heapspace″ condition; that is, at the
same time as the Java application receives an OutOfMemory error. This feature is
enabled by default. You can disable it by using the
IBM_JAVADUMP_OUTOFMEMORY=FALSE environment variable.
Interpreting a Javadump
The information that is provided in a Javadump file is essentially the same,
regardless of the platform on which you are running the JVM. However, certain
platforms might provide more information about fatal exceptions.
192 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
interpreting a Javadump
Notes:
1. In some conditions, information might be missing because of the nature of a
crash.
2. The cross-platform sections of the dump are fully documented in the z/OS
example. The Linux and Windows examples build on top of this to describe
platform specifics.
Javadump tags
The Javadump files contain tags. This metadata makes it easier to parse and
perform simple analysis on the contents of Javadump files. An example tag is:
1CIJAVAVERSION J2RE 1.4.2 IBM J9 2.2 z/OS s390x-64 build 20040819_1437_BHdSMr
Note: For the rest of the chapter, the tags are removed to aid readability.
A lock prevents more than one entity from accessing a shared resource. Each object
in Java has an associated lock (gained by using a synchronized block or method).
In the case of the JVM, threads compete for various resources in the JVM and locks
on Java objects.
A monitor is a special kind of locking mechanism that is used in the JVM to allow
flexible synchronization between threads. For the purpose of this section, read the
terms monitor and lock interchangeably.
To avoid having a monitor on every object, the JVM usually uses a flag in a class
or method block to indicate that the item is locked. Most of the time, a piece of
code will transit some locked section without contention. Therefore, the guardian
flag is enough to protect this piece of code. This is called a flat monitor. However,
if another thread wants to access some code that is locked, a genuine contention
has occurred. The JVM must now create (or inflate) the monitor object to hold the
second thread and arrange for a signaling mechanism to coordinate access to the
code section. This monitor is now called an inflated monitor.
------------------------------------------------------------------------
LOCKS subcomponent dump routine
===============================
194 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
interpreting a Javadump
The entry count can be higher than 1 because a thread could enter a synchronized
method more than once (for example when an application uses recursion).
That is: Thread 1 waits for B is locked by Thread 2 waits for A is locked by Thread
1..... - a cycle in the “waits for/locked by” graph.
Neither thread can proceed until the other releases the relevant lock; this cannot
happen. This situation could be more complex, involving three or more threads
with interdependent locks, but the principle remains the same. Other threads
usually end up blocked on one or other of the locks involved, thereby causing a
totally deadlocked Java application.
sys_mon_t:0x000000013AE8B410 infl_mon_t: 0x000000013AE8B450:
java/lang/Object@0000000108899168/0000000108899180: Flat locked by "Thread-2" (0x000000013AE04000),
entry count 1
Waiting to enter:
"Thread-3" (0x000000013AE8C600)
sys_mon_t:0x000000013AE8B458 infl_mon_t: 0x000000013AE8B498:
The above LOCKS component dump is an example of a deadlock. First notice that
Thread-3 is waiting to lock the java/lang/Object@0000000108899168/
0000000108899180 object. Now Thread-2 has the lock of this object. Conversely,
Thread-2 is waiting to lock java/lang/Object@00000001088A1288/
00000001088A12A0, which is held by Thread-3. This is a clear (and in this case
simple) deadlock.
sys_mon_t:0x000000013AD760E0 infl_mon_t: 0x000000013AD76120:
java/lang/Object@00000001088991A0/00000001088991B8: owner "Thread-3" (0x000000013AD78C00), entry count 1
Waiting to enter:
"Thread-5" (0x000000013AD7EF00)
"Thread-6" (0x000000013AD7F600)
Waiting to be notified:
"Thread-1" (0x000000013AD73900)
"Thread-2" (0x000000013AD74000)
"Thread-4" (0x000000013AD79300)
sys_mon_t:0x000000013AD761B8 infl_mon_t: 0x000000013AD761F8:
java/lang/Object@000000010889A370/000000010889A388: owner "Thread-5" (0x000000013AD7EF00), entry count 1
Waiting to be notified:
"Thread-3" (0x000000013AD78C00)
The dump formatter (see Chapter 26, “Using the dump formatter,” on page 223)
can also diagnose deadlocks.
The following Javadump sample output 1 (z/OS) section applies to Linux and
Windows also.
------------------------------------------------------------------------
TITLE subcomponent dump routine
===============================
Dump Event "gpf" (00002000) received
Date: 2004/08/23 at 11:21:17
Javacore filename: /u/mcculls/javacore.20040823.112117.16908826.txt
------------------------------------------------------------------------
GPINFO subcomponent dump routine
================================
OS Level : z/OS 06.00
Processors -
Architecture : s390x
How Many : 2
196 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
interpreting a Javadump (z/OS)
signal: 000000000000000B
Registers:
gpr0:0000000000000000
gpr1:0000000000000000
gpr2:000000013AD6D168
gpr3:00000000112D5A68
gpr4:00000001082FE780
gpr5:000000013AD33E00
gpr6:000000001278F658
gpr7:000000001120901E
gpr8:0000000000000007
gpr9:0000000000000000
gpr10:0000000108377D70
gpr11:000000013AD6D168
gpr12:0000000108300C60
gpr13:0000000108377D00
gpr14:0000000011208918
gpr15:0000000000000000
fpr0:41400000C8A848BF
fpr1:4580000000000000
fpr2:0000000000000000
fpr3:3FF0000000000000
fpr4:406F000000000000
fpr5:0000000000000000
fpr6:0000000000000000
fpr7:0000000000000000
fpr8:0000000000000000
fpr9:0000000000000000
fpr10:0000000000000000
fpr11:0000000000000000
fpr12:0000000000000000
fpr13:0000000000000000
fpr14:0000000000000000
fpr15:0000000000000000
psw0:0785040180000000
psw1:000000001278F67C
fpc:0000000000000000
VM flags:00000000
------------------------------------------------------------------------
ENVINFO subcomponent dump routine
=================================
J2RE 1.4.2 IBM J9 2.2 z/OS s390x-64 build 20040819_1437_BHdSMr (JIT enabled - r7_level20040818_1801)
Running as a standalone JVM
java -Xmx4m -classpath test -Xbootclasspath/p:fix.jar gpf
Java Home Dir: /u/mcculls/sdk/J1.4_64
Java DLL Dir: /u/mcculls/sdk/J1.4_64/bin
Sys Classpath: fix.jar;/u/mcculls/sdk/J1.4_64/lib/jclSC14/classes.zip;/u/mcculls/sdk/J1.4_64/
lib/core.jar;
/u/mcculls/sdk/J1.4_64/lib/charsets.jar;/u/mcculls/sdk/J1.4_64/lib/graphics.jar;
/u/mcculls/sdk/J1.4_64/lib/security.jar;/u/mcculls/sdk/J1.4_64/lib/ibmpkcs.jar;/u/mcculls/sdk/
J1.4_64/lib/ibmorb.jar;
/u/mcculls/sdk/J1.4_64/lib/ibmorbapi.jar;/u/mcculls/sdk/J1.4_64/lib/ibmjcefw.jar;
/u/mcculls/sdk/J1.4_64/lib/ibmjssefips.jar;
/u/mcculls/sdk/J1.4_64/lib/ibmjgssprovider.jar;/u/mcculls/sdk/J1.4_64/lib/ibmjsseprovider.jar;
/u/mcculls/sdk/J1.4_64/lib/ibmjaaslm.jar;
/u/mcculls/sdk/J1.4_64/lib/ibmjaasactivelm.jar;/u/mcculls/sdk/J1.4_64/lib/ibmcertpathprovider.jar;
/u/mcculls/sdk/J1.4_64/lib/server.jar;
/u/mcculls/sdk/J1.4_64/lib/xml.jar;
UserArgs:
-Xjcl:jclscar_22
-Dcom.ibm.oti.vm.bootstrap.library.path=/u/mcculls/sdk/J1.4_64/bin
-Dsun.boot.library.path=/u/mcculls/sdk/J1.4_64/bin
-Djava.library.path=/u/mcculls/sdk/J1.4_64/bin/j9vm/libjvm.so:/u/mcculls/sdk/J1.4_64/bin/j9vm:
/u/mcculls/sdk/J1.4_64/bin/:/u/mcculls/javasrc/bin:/u/mcculls/javasrc/bin/j9vm:
/lib:/usr/lib:.
-Djava.home=/u/mcculls/sdk/J1.4_64
-Djava.ext.dirs=/u/mcculls/sdk/J1.4_64/lib/ext
-Duser.dir=/u/mcculls
_j2se_j9
vfprintf 0x0000000108300060
-Xmx4m
-Xbootclasspath/p:fix.jar
-Dinvokedviajava
-Djava.class.path=test
vfprintf
-Xdump
.
v Arguments supplied when initializing the JVM labeled under UserArgs. For
example: -Djava.class.path=test.
198 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
interpreting a Javadump (z/OS)
The main diagnostic function of this section is to determine exactly what native
executables and Java classes were being run when the dump occurred. This can
include the java executable, the Java API, IBM extensions, and user application
class files.
The UserArgs section shows arguments for the JVM, which might have been
supplied by the user or generated during JVM initialization. For example, the
-Djava.class.path=test property was generated by the user specifying the option
-classpath test on the command-line. However, -Duser.dir=/u/mcculls was
generated automatically.
The bootclasspath (classpath of the bootstrap class loader) contains the locations
from which the Java API is loaded. This takes the default bootclasspath and is then
modified by any supplied arguments. In this case, the -Xbootclasspath/p:\fix.jar
argument adds fix.jar to the start of the default bootclasspath. The effect of this
is that the JVM will attempt to load classes (including the Java API) from
D:\fix.jar before
/u/mcculls/sdk/J1.4_64/lib/jclSC14/classes.zip;
/u/mcculls/sdk/J1.4_64/lib/core.jar;...
The classpath (generally refers to the system or application class loader’s classpath)
takes a default value of ″.″ (the working directory of Java). This causes the
-Djava.class.path=. property to be set by default. In this example, it is then
overridden by -Djava.class.path=test (generated from the command-line option
-classpath test). This example shows the case where a later value of a system
property replaces an earlier value in the system property list.
------------------------------------------------------------------------
THREADS subcomponent dump routine
=================================
Full thread dump J9SE VM (J2RE 1.4.2 IBM J9 2.2 z/OS s390x-64 build 20040819_1437_BHdSMr, native threads):
"main" (TID:0x0000000108377D00, sys_thread_t:0x0000000108315E28, state:R, native ID:0x1112F10000000001)
prio=5
at gpf.action(Native Method)
at gpf.main(gpf.java:8)
"[system]" (TID:0x0000000108378400, sys_thread_t:0x0000000108315F38, state:CW, native ID:0x11144B7000000003)
prio=11
"Signal Dispatcher" (TID:0x0000000119833A00, sys_thread_t:0x0000000108315FC0, state:R, native ID:0x11163C8000000004)
prio=5
at com/ibm/misc/SignalDispatcher.waitForSignal(Native Method)
at com/ibm/misc/SignalDispatcher.run(SignalDispatcher.java:78)
"Gc Slave Thread" (TID:0x0000000119834100, sys_thread_t:0x0000000108316158, state:CW, native ID:0x111669B000000007)
prio=5
A thread is alive if it has been started but not yet stopped. A Java thread is
implemented by a native thread of the operating system. Each thread is
represented by a line such as:
"main" (TID:0x0000000108377D00, sys_thread_t:0x0000000108315E28,
state:R, native ID:0x1112F10000000001) prio=5
The properties of a thread are name, identifier, JVM data structure address, current
state, native thread identifier, and priority. A large value for priority means that the
thread has a high priority. The values of state can be:
v R - Runnable - the thread is able to run when given the chance.
v CW - Condition Wait - the thread is waiting. For example, because:
– A sleep() call is made.
– The thread has been blocked for I/O.
– A synchronized method of an object locked by another thread has been called.
– The thread is synchronizing with another thread with a join() call.
v S – Suspended – the thread has been suspended by another thread.
v Z – Zombie – the thread has been killed.
Below each thread there is a stack trace for that thread. A stack trace is a
representation of the hierarchy of Java method calls made by the thread. For
example:
200 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
interpreting a Javadump (z/OS)
------------------------------------------------------------------------
CLASSES subcomponent dump routine
=================================
Classloader summaries
12345678: 1=primordial,2=extension,3=shareable,4=middleware,5=system,6=trusted,7=application,8=delegating
p---st-- Loader *System*(0x00000001088476C0)
Number of loaded classes 274
-x--st-- Loader sun/misc/Launcher$ExtClassLoader(0x000000010884EE70), Parent *none*(0x0000000000000000)
Number of loaded classes 0
-----ta- Loader sun/misc/Launcher$AppClassLoader(0x0000000108864A58), Parent sun/misc/Launcher$ExtClassLoader(0x000000010884EE70)
Number of loaded classes 1
ClassLoader loaded classes
Loader *System*(0x00000001088476C0)
java/security/UnresolvedPermission(0x000000013AD54018)
java/security/BasicPermissionCollection(0x000000013AD54A58)
java/security/Principal(0x000000013AD55218)
[Ljava/security/Principal;(0x000000013AD553C8)
....................left out to save space....................
java/lang/OutOfMemoryError(0x0000000108CB1C00)
java/util/Dictionary(0x0000000108CB1E60)
Loader sun/misc/Launcher$ExtClassLoader(0x000000010884EE70)
Loader sun/misc/Launcher$AppClassLoader(0x0000000108864A58)
gpf(0x000000013AD6D068)
Final section
This section gives confirmation that the file is complete.
------------------------------------------------------------------------
Javadump End section
Javadump Buffer Usage Information
=================================
Javadump buffer size (allocated): 2621440
Javadump buffer size (used) : 27752
---------------------- END OF DUMP -------------------------------------
Module: ./libgpf.so
Module_base_address: 0000007FBFFFDA50
Symbol: Java_gpf_action
Symbol_address: 0000000000000001
Registers:
rdi:000000004011E600
rsi:000000004038B068
rax:0000000000000000
rbx:0000000000000110
rcx:000000004015A5E2
rdx:000000004015A5D0
rbp:0000007FBFFFF170 r8:000000004015A5E7
r9:000000004015A5D0
r10:0000000000000000
r11:0000000000000000
r12:0000000000000002
r13:0000000001000109
r14:0000002A96090200
r15:0000002AB8ED1898
rip:0000002AB8ED18B0
rsp:0000007FBFFFF170
eflags:0000000000010246
cs:0000000000000033
fs:0000000000000000
gs:0000000000000000
VM flags:00000000
On Linux, this section gives more detailed information about the location of the
crash (for example the failing module) along with the register listing.
ExceptionCode: 00000000C0000005
ExceptionAddress: 000007FF8A89105A
ContextFlags: 000000000010001F
202 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
interpreting a Javadump (Windows)
Handler1: 00000000112027A0
Handler2: 0000000010026BB0
Module: E:\mcculls\test\gpf.dll
Module_base_address: 000007FF8A890000
Offset_in_DLL: 000000000000105A
Registers:
RDI:0000000000000000
RSI:0000000000000007
RAX:0000000000000000
RBX:0000000000000110
RCX:000007FFFFC00A00
RDX:000007FF8D040CF8
RBP:000007FFFFF7FCD0
R8:0000000000000000
R9:000007FFFFF7FCD0
R10:0000000000000000
R11:000007FF8D040DA0
R12:0000000001000109
R13:000007FF8A891005
R14:00000000100466A0
R15:000007FFFFF7F8C0
RIP:000007FF8A89105A
RSP:000007FFFFF7F8A0
VM flags:00000000
On Windows this section gives more detailed information about the location of the
crash (for example the failing module) along with the register listing.
204 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 22. Using Heapdump
This chapter describes:
v “Summary of Heapdump”
v “Information for users of previous releases of Heapdump”
v “Enabling a Heapdump”
v “Location of the generated Heapdump” on page 207
v “Producing a Heapdump using jdmpview” on page 207
v “Available tools for processing Heapdumps” on page 208
v “Using VerboseGC to obtain heap information” on page 208
Summary of Heapdump
The term Heapdump is used to describe the IBM Virtual Machine for Java
mechanism that generates a dump of all the live objects that are on the Java heap;
that is, those that are being used by the running Java application. From Version
1.4.2 Service Refresh 2, this dump is stored in a file (using the phd format). You
can use various tools on the Heapdump output to analyze the composition of the
objects on the heap and (for example) help to find the objects that are controlling
large amounts of memory on the Java heap and the reason why the Garbage
Collector cannot collect them.
Enabling a Heapdump
You can generate a Heapdump from a running JVM in either of two ways:
v Explicit generation
v JVM-triggered generation
When the Java heap is exhausted (that is, the OutOfMemory condition is
encountered and the resulting exception is not caught or handled by the
application), JVM-triggered generation is enabled by default, as are Heapdumps
that are generated by other programming methods. To enable signal-based
Heapdumps, set the IBM_HEAPDUMP or IBM_HEAP_DUMP environment
variable to any value,
export IBM_HEAPDUMP=<any_value>
export IBM_HEAP_DUMP=<any_value>
or set the appropriate JAVA_DUMP_OPTS before you start the Java process. You
can also use the -Xdump agent option to get more fine-grained control over
Heapdumps. See Chapter 24, “Using dump agents,” on page 213 for more
information.
To display on JVM startup the conditions (if any) that will generate a Heapdump
(or javadump or systemdump), you can use -Xdump:what. See Chapter 24, “Using
dump agents,” on page 213 for more information.
On Windows, use:
set IBM_HEAPDUMP=
set IBM_HEAP_DUMP=
You can explicitly request a Heapdump in the same way as a Javadump. Before the
Heapdump starts, the heap is locked and remains locked until the whole
Heapdump file is written to disk. This operation can affect the behavior of your
Java application, and make it unresponsive while the dump is being produced.
For Linux, send the JVM the signal SIGQUIT (kill -3, or Ctrl+\ in the console
window).
You can explicitly request a Heapdump from a Java method. The class
com.ibm.jvm.Dump contains a static HeapDump() method that causes Java code to
initiate a Heapdump.
The first option is enabled by default, and you can see it with -Xdump:what. It
gives a snapshot of the Java heap when no more memory is available. Usually, this
snapshot is the most useful output to help you determine the cause of an
OutOfMemory condition that is related to the Java heap. It works independently of
the IBM_HEAPDUMP environment variable. So, by default, you get Heapdumps
only when no more heap space is available; you do not get Heapdumps in crashes
or through a signal to the JVM. You can disable this feature, and a similar one for
Javadumps, by using IBM_HEAPDUMP_OUTOFMEMORY=FALSE and
IBM_JAVADUMP_OUTOFMEMORY=FALSE respectively.
206 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Enabling a Heapdump
IBM_HEAPDUMP_OUTOFMEMORY=TRUE and
IBM_JAVADUMP_OUTOFMEMORY=TRUE respectively.
where:
v %pid is the process ID
v .%Y%m%d.%H%M%S is the date and time
Notes:
1. If ″Classic″ Heapdump is enabled, the name of the Heapdump will end in txt
rather than phd.
2. You can override the standard names by use of the label= parameter. See
Chapter 24, “Using dump agents,” on page 213 for more information.
java -verbosegc
208 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 23. JVM dump initiation
The JVM supports the ability to generate a native system dump. In addition, a
very simple scripting ability allows you to choose when and how a dump is
generated. The exact dump created is, by definition, platform-dependent. The way
you proceed with analysis of the dump depends on the platform tools that are
available. A short description of how to proceed with the JVM native dump is
provided.
Overview
The JVM might produce dump files in response to specific events, depending on
the setting of the environment variables JAVA_DUMP_OPTS and
JAVA_DUMP_TOOL, as well as any -Xdump agent options specified on the
command line; see Chapter 24, “Using dump agents,” on page 213 for more
information.
The types of dump that can be produced (platform-specific variations are noted
below) are:
1. SYSDUMP. An unformatted dump that the operating system generated
(basically a core file).
2. HEAPDUMP. An internally generated dump of the objects that are on the Java
heap.
3. User specified. Whatever the JAVA_DUMP_TOOL variable specifies.
4. JAVADUMP. An internally generated and formatted analysis of the JVM.
If all types of dump are requested, they are produced in the above sequence
(JAVADUMP always being last). You can read system dumps by using native
dump analysis tools (IPCS, dbx, and so on), although they can also be processed in
a platform-independent way using jextract and the JVM Dump Formatter.
SYSDUMP file names and locations vary with each platform and are detailed
below. For more information about JAVADUMP files, see Chapter 21, “Using
Javadump,” on page 191.
If any external dump exit routines have been registered, they are run before the
main JVM dump sequence (see above), and can optionally terminate all further
dump processing by returning RAS_DUMP_ABORT.
Settings
In the absence of overrides from the -Xdump option on the command line starting
the JVM (see Chapter 24, “Using dump agents,” on page 213), the dumps that are
produced for each condition are determined primarily by the JAVA_DUMP_OPTS
environment variable as follows:
JAVA_DUMP_OPTS="ONcondition(dumptype,dumptype),ONcondition(dumptype,...),...)
where:
v condition can be:
– ANYSIGNAL
– DUMP
– ERROR
– INTERRUPT
– EXCEPTION
– OUTOFMEMORY
v and dumptype can be:
– ALL
– NONE
– JAVADUMP
– SYSDUMP
– HEAPDUMP
210 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JVM dump - settings
If %pid is detected in the string, the string is replaced with the JVM’s own process
ID. The tool specified by JAVA_DUMP_TOOL is run after any system or heap
dump has been taken, but before anything else.
Platform-specific variations
Conditions can be mapped to different signals on different platforms, and some
signals are recognized on some platforms but not on others. Table 9 shows the
mapping across platforms. Note that if the JVM receives a signal that it does not
recognize (that is, it is not mapped to a condition as listed in the table), the default
operating system action for that signal is taken. Usually the signal is ignored.
Table 9. Signal mappings on different platforms
z/OS Windows Linux
EXCEPTION SIGTRAP SIGTRAP
SIGILL SIGILL SIGILL
SIGSEGV SIGSEGV SISEGV
SIGFPE SIGFPE SIGFPE
SIGBUS SIGBUS
SIGSYS
SIGXCPU SIGXCPU
SIGXFSZ SIGXFSZ
If a signal is not handled by the JVM, the operating system takes its default action
for that signal. In the case of an EXCEPTION type signal, it is most likely to
produce a system dump.
z/OS
The full syntax for JAVA_DUMP_OPTS on z/OS is:
JAVA_DUMP_OPTS="ONcondition(dumptype,dumptype),ONcondition
(dumptype,...),...)"
v CEEDUMP
v HEAPDUMP (see Chapter 22, “Using Heapdump,” on page 205)
Under z/OS, you can change the behavior of LE by setting the _CEE_RUNOPTS
environment variable (for details refer to the LE Programming Reference). In
particular, the TRAP option determines whether LE condition handling is enabled,
which, in turn, drives JVM signal handling, and the TERMTHDACT option
indicates the level of diagnostic information that LE should produce.
Windows
Dumps are produced in the following form:
v SYSDUMP: Output is written to a file named core.%Y%m%d.%H%M%S.
%pid.dmp into the same directory that is used for JAVADUMP.
v JAVADUMP: Output is written to a file named a file named
javacore.%Y%m%d.%H%M%S.%pid.txt. See Chapter 21, “Using Javadump,” on
page 191 for more information.
v HEAPDUMP: The raw heap image is written to a file named
heapdump.%Y%m%d.%H%M%S.%pid.phd. See Chapter 22, “Using Heapdump,”
on page 205 for more information.
Linux
Dumps are produced in the following form:
v SYSDUMP: Output is written to a file named core.%Y%m%d.%H%M%S.
%pid.dmp into the same directory that is used for JAVADUMP.
v JAVADUMP: Output is written to a file named javacore.%Y%m%d.%H%M%S.
%pid.txt. See Chapter 21, “Using Javadump,” on page 191 for more information.
v HEAPDUMP: The raw heap image is written to a file named
heapdump.%Y%m%d.%H%M%S.%pid.phd . See Chapter 22, “Using
Heapdump,” on page 205for more information.
212 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 24. Using dump agents
Dump agents are set up during JVM initialization. They enable you to use events
occurring within the JVM, such as Garbage Collection, thread start, or JVM
termination, to initiate one of four types of dump or to launch an external tool.
There are default dump agents set up at JVM initialization, which will suffice in
most cases, but the use of the -Xdump option on the command line allows more
detailed configuration of dump agents. The total set of options and suboptions
available under -Xdump is very flexible and there are many examples presented in
this chapter to show this flexibility.
The -Xdump option allows you add and remove dump agents for various JVM
events, update default dump settings (such as the dump name), and limit the
number of dumps that are produced.
Help options
You can obtain help on the various usage aspects of -Xdump by using java
-Xdump:help.
Table 10. Usage from java -Xdump:help
Command Result
-Xdump:help Print general dump help
-Xdump:none Ignore all previous and default dump
options
-Xdump:events List available trigger events
-Xdump:request List additional VM requests
-Xdump:tokens List recognized label tokens
-Xdump:what Show registered agents on startup
-Xdump:<type>:help Print detailed dump help
-Xdump:<type>:none Ignore previous dump options of this type
-Xdump:<type>:defaults Print and update default settings for this
type
-Xdump:<type> Request this type of dump (using defaults)
As an example:
java -Xdump:heap:none -Xdump:heap:events=fullgc class [args...]
turns off default Heapdumps and then requests a Heapdump on every full GC.
As can be seen from Table 10 on page 213, further help is available for the assorted
suboptions under -Xdump. In particular, java -Xdump:events shows the available
keywords used to specify the events that can be used.
You must filter class events (such as load, throw, and uncaught) by class name. For
guidance, see “Limiting dumps using filters” on page 218.
Table 12. Keywords
Supported event keywords Event hook
gpf ON_GP_FAULT
user ON_USER_SIGNAL
abort ON_ABORT_SIGNAL
vmstart ON_VM_STARTUP
vmstop ON_VM_SHUTDOWN
load ON_CLASS_LOAD
unload ON_CLASS_UNLOAD
throw ON_EXCEPTION_THROW
brkpoint ON_BREAKPOINT
framepop ON_DEBUG_FRAME_POP
thrstart ON_THREAD_START
blocked ON_THREAD_BLOCKED
thrstop ON_THREAD_END
expand ON_HEAP_EXPAND
fullgc ON_GLOBAL_GC
uncaught ON_EXCEPTION_DESCRIBE
slow ON_SLOW_EXCLUSIVE_ENTER
any *
214 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Dump types and triggering
happens. The JVM is constructed to generate at the appropriate time the events
listed in Chapter 23, “JVM dump initiation,” on page 209.
You can have multiple -Xdump stanzas on the command line and also multiple
dump types driven by one or multiple events. Thus,
-Xdump:heap+java:events=vmstart+vmstop would create a dump agent that
would drive both heap and Java dump production when either a vmstart or
vmstop event was encountered.
Note that multiple -Xdump stanzas on the command line can be used to create
multiple agents at JVM initialization; these agents are chained together and all
evaluated whenever an event occurs. The dump agent processing ensures that
multiple -Xdump stanzas are optimized. You can use the -Xdump:what stanza to
clarify this optimization.
The keyword events is used as the prime trigger mechanism. However, there are a
number of additional keywords that you can use to further control the dump
produced (request and tokens, for example) or limit its production to a smaller
range of circumstances; use -Xdump<type>:help to find these.
As you can see from using -Xdump:help, there are five dump types to consider.
Console dumps
Console dumps are simple dumps, in which the status of every Java thread is
written to stderr. Some output of this type is shown below. Note the use of the
range=1..1 suboption to control the amount of output to just one thread start and
stop (in this case, the start of the Signal Dispatcher thread).
java -Xdump:console:events=thrstart+thrstop,range=1..1
ThreadName=Signal Dispatcher(00035B24)
Status=Running
ThreadName=main(00035A1C)
Status=Waiting
Monitor=00035128 (VM sig quit)
Count=0
Owner=(00000000)
^^^^^^^^ Console dump ^^^^^^^^
System dumps
System dumps involve dumping a whole frozen address space and as such are
generally very large. The bigger the footprint of an application the bigger its
dump. A dump of a major server-based application might take up many gigabytes
of file space and take several minutes to complete. Shown below is an example of
invoking a system dump on a Windows 32-bit machine. Note the use of
request=nodumps+exclusive+prepwalk in this example, to ensure that this dump
is not interrupted by other dumps and that the Java heap is walkable, enabling the
objects within the heap to be processed under jextract or jdmpview (the equivalent
of -Xdump:heapdump in the previous release). Note also that the file name is
overridden from the default in this example.
java -Xdump:system:events=vmstop,request=nodumps+exclusive+prepwalk,file=my.dmp
Tool option
The tool option allows external processes to be spawned when an event occurs.
Consider the following simple example, which displays start of pid and end of pid
information (note the use of the token %pid). More realistic examples would
invoke a debugging tool, and that is the default taken if you use (for example)
-Xdump:tool:events=.....
java -Xdump:tool:events=vmstop,exec="cmd /c echo %pid has finished"
-Xdump:tool:events=vmstart,exec="cmd
Javadumps
Java dumps are an internally generated and formatted analysis of the JVM, giving
information that includes the Java threads present, the classes loaded, and heap
statistics. An example (which also shows the use of the filter keyword) in which a
Javadump is produced on the loading of a class is shown below.
java -Xdump:java:events=load,filter=*ZipC
Heapdumps
From Version 1.4.2, Service Refresh 2, Heapdumps now produce phd format files
by default (as described in Chapter 22, “Using Heapdump,” on page 205) unless
overridden. The example below shows the production of a Heapdump. Note that
in this case the normal production of a phd file only has been augmented by the
use of the opts= suboption to produce both phd and classic (.txt) heapdumps
(equivalent to using the environment variable IBM_JAVA_HEAPDUMP_TEST).
216 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Types of dump agents - examples
-Xdump:<type>:defaults
You can change these defaults at runtime. For example, to guarantee unique files
you would use:
-Xdump:java:defaults:file=dumps/%pid/javacore-%seq.txt
Note that this option does not add a javadump agent; it updates the default
settings for dump agents. Further dump agents will then create dump files using
this specification for filenames, unless overridden.
You can filter class events (such as load, throw, and uncaught) by class name:
-Xdump:java:events=throw,filter=java/lang/OutOfMem # prefix
-Xdump:java:events=throw,filter=java/lang/*Memory # substring
You can filter the JVM shutdown event by using one or more exit codes:
-Xdump:java:events=vmstop,filter=#129..192#-42#255
You can start and stop dump agents on a particular occurrence of a JVM event by
using the range suboption:
-Xdump:java:events=fullgc,range=100..200
-Xdump:none
Use this option so that you can subsequently specify a completely new dump
configuration.
You can also remove dump agents of a particular type. For example,
-Xdump:java+heap:events=vmstop -Xdump:heap:none
turns off all heapdumps (including default agents) but leaves javadump enabled.
218 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 25. Using method trace
Method trace is a powerful and free tool that allows you to trace methods in any
Java code. You do not have to add any hooks or calls to existing code. Run the
JVM with method trace turned on and watch the data that is returned. Using
method trace provides a complete (and potentially large) diagnosis of code paths
inside your application and also inside the system classes. Use wild cards and
filtering to control method trace so that you can focus on the sections of code that
interest you.
Use method trace to debug and trace application code and the system classes
provided with the JVM.
Method trace is part of the larger ’JVM trace’ package. JVM trace is described in
Chapter 30, “Tracing Java applications and the JVM,” on page 259.
This chapter describes the basic use of trace. Use this chapter to learn the basic use
of trace. When you feel comfortable using trace, see Chapter 30, “Tracing Java
applications and the JVM,” on page 259 for more detailed information.
Use the methods parameter to control what is traced. To trace everything, set it to
methods=*.*. This is not recommended because you are certain to be overwhelmed
by the amount of output.
Note that
v The delimiter between parts of the package name is a forward slash, ’/’, even on
platforms like Windows that use a backward slash as a path delimiter.
v The ″!″ in the methods parameter is a NOT operator that allows you to tell the
JVM not to trace the specified method or methods. Use this with other methods
parameters to set up a trace of the form: ″trace methods of this type but not
methods of that type″.
v The parentheses, (), that are in the method_spec define whether or not to trace
method parameters.
Examples of use
v Tracing entry and exit of all methods in a given class:
-Xtrace:methods=ReaderMain.*
methods=java/lang/String.*
v Tracing entry, exit and input parameters of all methods in a class:
-Xtrace:methods=ReaderMain.*()
v Tracing all methods in a given package:
-Xtrace:methods=com/ibm/socket/*.*()
v Multiple method trace:
-Xtrace:methods=Widget.*(),common/Gauge.*
This traces all method entry, exit, and parameters in the Widget class and all
method entry and exit in the Gauge package.
v Using the ! operator
-Xtrace:methods=ArticleUI.*,!ArticleUI.get*
This traces all methods in the class ArticleUI except those beginning with “get”.
Advanced options
The use of method trace described above forces a formatted version of the output,
however, it can be rather slow. To work around this, you can make the method
trace output appear in a compressed binary form and thus minimize its impact on
performance. You can then redirect this form of the output to an output file, rather
than only to the console as in the description above.
You use a tool, supplied with the IBM Virtual Machine for Java, to analyze and
dump the output binary file. You can even route trace to your own plug-in agent
and process it at will (see Chapter 30, “Tracing Java applications and the JVM,” on
page 259).
Real example
java-Xtracemethods=ReaderMain.*(),ConferenceUI.*() -Dibm.dg. trc.print=mt ReaderMain
Results:
java -Xtrace:methods=java/lang*.*,iprint=mt HW
15:33:44.786*0xa0900 040001 > java/lang/Class.initialize()V Compiled method, This = 0x1552b4
15:33:44.796 0xa0900 040001 > java/lang/Class.verify()V Compiled method, This = 0x15528c
15:33:44.796 0xa0900 040001 > java/lang/Class.verify()V Compiled method, This = 0x155260
15:33:44.796 0xa0900 040001 > java/lang/Class.setInitStatus(I)V Compiled method, This = 0x155234
15:33:44.796 0xa0900 040007 < java/lang/Class.setInitStatus(I)V Compiled method
15:33:44.796 0xa0900 040007 < java/lang/Class.verify()V Compiled method
15:33:44.796 0xa0900 040001 > java/lang/Class.setInitStatus(I)V Compiled method, This = 0x155260
15:33:44.796 0xa0900 040007 < java/lang/Class.setInitStatus(I)V Compiled method
15:33:44.796 0xa0900 040007 < java/lang/Class.verify()V Compiled method
220 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Method trace - examples of use
222 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 26. Using the dump formatter
v “What the dump formatter is”
v “Problems to tackle with the dump formatter” on page 224
v “Supported commands” on page 224
v “Example session” on page 229
jextract sends its output to a file called dumpfilename.xml. This file contains
details of useful JVM internal information. Note that the syntax of the xml is
subject to change so you should not design tools based on the contents of this
xml file. Preferably, you should run jextract on the same system as the one on
which the dump was produced. However, you can run jextract on a system
that has the same version of the JRE as the system on which the dump was
produced.
jdmpview
jdmpview is a launcher for the main method of the java class J9JVMConsole
that is contained in the sdk/jre/lib/ext/jdmpview.jar. To invoke jdmpview,
from a command prompt type:
jdmpview [-ddumpfilename] [-wworkdir] [-ooutput]
where
v dumpfilename is a dumpfile
v workdir is a writable directory
v output is an output file (typical format file:x:\myfile)
Typical usage is jdmpview my.dmp. The J9JVMConsole class opens and verifies
the my.dmp file (which it recognizes as a dump file) and the associated xml
file (my.dmp.xml).
After jdmpview processes the arguments with which it was launched, it
displays the message Ready.... This means that you can start invoking
commands on jdmpview. There is no limit on the number of jdmpview
sessions that you can run at the same time.
You can significantly improve the performance of jdmpview against larger
dumps by ensuring that there is enough memory available on your system to
avoid paging. On larger dumps (that is, ones with large numbers of objects on
the heap) you might have to invoke jdmpview using the -Xmx option to
increase the maximum heap available to jdmpview:
jdmpview -J-Xmx<n>
For problems involving gprs, ABENDS, SIGSEVs, and similar problems, you can
get more information by using the system debugger (windbg, gdb) along with the
dump file. However, jdmpview can still provide useful information in conjunction
with the system debugger.
Supported commands
This section describes the commands available in jdmpview. Many of the
commands have short forms. For example, display, dis, and d are all considered
equivalent in the standard command syntax. The commands are split into common
subareas.
General commands
v Quit
Short form: q
Availability: always
Terminates the jdmpview session.
v cmds
Short form:
Availability: always
Displays the available commands at any point during the jdmpview session and
also indicates which class provides the support for that command. Note that the
range of available commands might change during the session; for example, the
DIS OS command is not available until after a dump has been identified.
v help and help <command>
Short form: h
Availability: always
224 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Supported commands
The help command (with no parameters) shows general help. With a parameter
it displays specific help on a command. For example, help dis os would
produce help information regarding the help dis os command.
v set
Short form: s
Availability: always
Some set commands (such as set dump) initiate specific processing within
jdmpview while others set and unset variables within the jdmpview
environment. The variations of set are covered below.
set without any parameters shows what jdmpview variables are defined and
what their values are. Similarly, set param shows the value of param. The
generic command set param=value sets up a key/value pair associating the value
with the key param. Parameters can be used for remembering discovered values
for later use.
v set dump
Short form: s du
Availability: always
Opens the specified dump. The syntax is:
set dump[=]<dumpname>
After the set dump command has executed successfully, several additional
commands (such as dis mem and dis mmap) become available. When set dump
has successfully run (i.e. it was a valid file and it was a dump), another use of
set dump does nothing. If you want to analyze another dump, you must start a
new jdmpview session.
v set metadata
Short form: s meta
Availability: after successful ″set dump″
Initiates the reading of the xml file produced by jextract, causes the xml file to
be parsed, and assorted details about the underlying nature of the dump stored
for use by other commands (such as dis os or dis cls). The syntax is
set metadata[=]<filename>
After set metadata has successfully run, subsequent uses of it will do nothing.
v set workdir
Short form:
Availability: always
Identifies a location to which jdmpview can write data. Some commands (such
as dis os or trace extract) create files as part of their function – usually these
files are created in the same location as the dumpfile; however sometimes it
might be convenient to keep the dumpfile (and the xml) in a read-only location.
Its syntax is:
set workdir[=]<location>
You can also use the –w option when launching jdmpview to set the working
directory.
v set output
Short form: s out
Availability: always
Redirects the output from jdmpview to a file rather than to the console
(System.out). Use it when large amounts of output are expected to be produced
from a command (for example, dis mem 10000,100000). Its syntax is:
set output[=]<location>
226 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Supported commands
where <address> is the hex address to display (it can be preceded by 0x) and
<numbytes> (defaults to 256) is the number of bytes to display.
v find
Short form: fn
Availability: after set dump has run
Looks for strings and hex values within the dump memory. The syntax is
Find pattern[,<start>][,<end>][,<boundary>][,<count>][,<limit>]
The <start> parameter controls where to start the search from, <end> where to
end it , <boundary> what byte boundary should be used, <count>how many
bytes of memory should be displayed when a hit is encountered, and <limit>
the limit of occurrences to display.
228 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Supported commands
Example session
This example session is meant to illustrate some of the commands available and
their use. In the example session below some lines have been removed for clarity
(and shortness). Some comments (contained within braces) are included to explain
various aspects together with some comments on individual lines looking like
<< comment
jdmpview c:\dl2.dmp
Ready....(’h’ shows help, ’cmds’ shows available commands) << jdmpview is ready
to accept user input
h
General Help
===============
To see what commands are available use the "cmds" command.
Note: The available command set can change as a result of some actions
- such as "set dump" or "set metadata".
The general form of a command is NOUN VERB PARM1 [,PARM2] ... [PARMn]
Note: some commands dont need a verb or parameters. The command parser
strips "=" characters and brackets from the input - this allows
alternative command formats like "set dump=c:\mydump.dmp" to work.
Ready....
As part of the processing when "set dump" is issued then if an xml file (as
produced out of jextract)is found matching the dump then a "set metadata"
command will be issued.
Ready....
{ The next command illustrated is "cmds" – this shows the syntax of the
currently recognised commands}
cmds
Known Commands
==============
230 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Example session
Ready....
{ The next command "dis os" is covered below – this command scans
the heap segments that were identified in the xml and produces a
names index file (.jfod) to allow subsequent
anlaysis of objects. For large dumps with several millions of
objects then this command could take a long time.
Following "dis os" is an alternative form of dis os where a
class name is specified. This allows the
addresses of all objects of a specific type to be displayed –
which could then be used as input to "dis obj" }
dis os
Heap Summary
============
WARNING: It can take a long time to traverse the heaps!!!! - Please be patient
Starting scan of heap segment 0
start=0x13710000 end=0x1371070c object count= 45
Starting scan of heap segment 1
start=0x13710800 end=0x13712424 object count= 21
Object Summary
Deadlock has 1 instances (total size= 72)
[java/lang/Object has 33 instances (total size= 1881)
[java/lang/Class has 10 instances (total size= 180)
[char has 2189 instances (total size= 199199)
[double has 10 instances (total size= 560)
[byte has 78 instances (total size= 257946)
[short has 3 instances (total size= 8784)
[int has 66 instances (total size= 8976)
Ready....
dis os java/lang/String
There are 2046 instances of java/lang/String ....
Ready....
{ "dis mmap" is used to show what memory ranges are available in the dump.}
dis mmap
Memory Map
==========
Addr: 0x00010000 Size: 4096 File Offset: 0x4054 (16468)
Addr: 0x00020000 Size: 4096 File Offset: 0x5054 (20564)
Addr: 0x00030000 Size: 49152 File Offset: 0x6054 (24660)
Addr: 0x0007d000 Size: 16384 File Offset: 0x12054 (73812)
Addr: 0x00090000 Size: 1073152 File Offset: 0x16054 (90196)
================= lines removed for terseness ======================
Addr: 0x13710000 Size: 4194304 File Offset: 0xdff054 (14676052)
================= lines removed for terseness ======================
Addr: 0x629c0000 Size: 32768 File Offset: 0x11ff054 (18870356)
Addr: 0x71aa0000 Size: 32768 File Offset: 0x1207054 (18903124)
Ready....
{ dis mem <address> is used to show memory contents, and +/- allows movement
forwards and backwards from that memory position}
232 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Example session
Ready....
+
Ready....
{ "find <text>" is used to find text in memory or (if the value starts with
0x then you can find byte sequences}
find java
Note: your search result limit was 1 ... there may be more results
Find finished...
Ready....
{To display details of an object then the "dis obj" command is used, either
in the form shown below where only a class name is specified (there might be a
large number of different objects of this class) or in the form dis obj 0xhhhhhhh
for just one}
====================================================
Ready....
{To examine all the threads in the dump – "dis t *" is used. dis t can be used to
examine the current thread, and dis t 0cxhhhhh to examine a particular thread –
set t will show you the available threads}
dis t *
Info for thread - 0x9ff00
===============================
Name : main
Id : 0x9ff00
Obj : 0x1371036c (java/lang/Thread)
State : Blocked MonitorId: 0x35050
Stack:
methodId: 0x2ec19a8 pc: 0x2e99c65 arguments: 0x29830e4
===> Deadlock/main([Ljava/lang/String;)V
234 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Example session
Ready....
{If monitors (also known as locks) are of interest – then "dis ls" is used }
dis ls
Known Monitors....
Thread global
id= 0x342c0
MM_SublistPool
id= 0x34330
Un-named Monitor@0x34fa8
id= 0x34fa8
Locked Objects.....
Ready....
{There is also a deadlock command which analyses the locks for deadlock
situations - see the example below. }
deadlock
Ready....
{The heapdump (hd) command is used to produce output for the heapdump tool
(see Heapdump chapter. an example of the hd command is shown below, in this
case it is producing a file which contains details of all the objects found
in the dump and all their associated references).
hd f
Now dumping heapdump file c:\dl2.dmp.phd.gz
Ready....
q
Quitting - bye
236 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 27. JIT problem determination
The Just-In-Time compiler (JIT) is tightly bound to the JVM, but is not part of it.
The JIT converts Java bytecodes, which are interpreted by the JVM at run time and
execute slowly, into native code, which is understood by the processor and
executes quickly.
Occasionally, valid bytecodes might compile into invalid native code, causing the
Java program to fail. By determining whether the JIT is faulty and, if so, where it is
faulty, you can provide valuable help to the Java service team.
This chapter describes how you can determine with reasonable certainty whether
your problem is JIT-related. This chapter also suggests some possible workarounds
and debugging techniques for solving JIT-related problems:
v “Disabling the JIT”
v “Selectively disabling the JIT”
v “Locating the failing method” on page 238
v “Identifying JIT compilation failures” on page 239
v “Performance of short-running applications” on page 240
The call count mechanism spreads compilation of methods throughout the life of
an application, giving higher priority to methods that are used most frequently.
Some infrequently used methods might never be compiled at all. As a result, when
a Java program fails, the problem might be in the JIT, or it might be elsewhere in
the JVM. The first step in diagnosing the failure is to determine where the problem
is. To do this, you must first run your Java program in purely interpreted mode
(that is, with the JIT disabled): specify the -Xint option, and remove the -Xjit
option (and accompanying JIT parameters, if any) when you run the JVM. If the
failure still occurs, the problem is most likely in the JVM rather than the JIT. (Do
not use the -Xint and the -Xjit options together.)
Running the Java program with the JIT disabled leads to one of the following:
v The failure remains. The problem is, therefore, not in the JIT. Do not read further
in this chapter. In some cases, the program might start failing in a different
manner; nevertheless, the problem is not related to the JIT.
v The failure disappears. The problem is most likely, although not definitely, in the
JIT.
The JIT optimizes methods at various optimization levels; that is, different
selections of optimizations are applied to different methods, based on their call
counts. Methods that are called more frequently are optimized at higher levels. By
changing JIT parameters, you can control the optimization level at which methods
are optimized, and determine whether the optimizer is at fault and, if it is, which
optimization is problematic.
runs the HelloWorld program, while enabling verbose output from the JIT, and
making it generate native code without performing any of the optimizations listed
in “How the JIT optimizes code” on page 30.
The JIT parameters give you a powerful tool that enables you to determine the
location of a JIT problem; whether it is in the JIT itself or in a few lines of code
that cause the JIT to fail. In addition, when you have identified a problem area,
you are automatically given a workaround so that you can continue to develop or
deploy code while losing only a fraction of JVM performance.
The first JIT parameter to try is count=0, which sets the JIT threshold to zero and
effectively causes the Java program to be run in purely compiled mode.
If the failure still occurs, try disableInlining. With this parameter set, the JIT is
prohibited from generating larger and more complex code in an attempt to
perform aggressive optimizations.
If the failure persists, try decreasing JIT optimization levels. The various
optimization levels are:
1. scorching
2. veryHot
3. hot
4. warm
5. cold
6. noOpt
Try each of the optimization levels in turn, and record your observations. If one of
these settings causes your failure to disappear, you have a quick workaround that
you can use while the Java service team analyzes and fixes the JIT problem. If you
can remove disableInlining from the JIT parameter list (that is, if removing it does
not cause the failure to reappear), do so to improve performance.
238 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JIT problem determination
optLevel=noOpt, you can also instruct the JIT to not compile the method or
methods that are causing the failure (thus avoiding it).
To locate the method that is causing the failure, follow these steps:
1. Run the Java program with the JIT parameters verbose and vlog=filename. With
these parameters, the JIT reports its progress, as it compiles methods, in a
verbose log file, also called a limit file. A typical limit file contains lines that
correspond to compiled methods, like:
+ (hot) java/lang/Math.max(II)I @ 0x10C11DA4-0x10C11DDD
Lines that do not start with the plus sign are ignored by the JIT in the steps
below, so you can edit them out of the file.
2. Make a backup of the limit file.
3. Delete some lines from the limit file, and run the program again with the JIT
parameter limitFile=filename, where filename is the path to the limit file. This
parameter causes the JIT to compile only the methods listed in the limit file.
Repeat this if the program still fails.
The recommended number of lines to delete from the limit file in each
repetition is half the file, so that this step is essentially a binary search for the
failing method. Since lines that do not start with a plus sign are ignored, you
can also comment out lines rather than delete them, by inserting a space or a
minus sign at the beginning of the lines you wish to remove.
4. If the program no longer fails, then one or more of the methods that you have
removed in the last iteration must have been the cause of the failure. Empty the
current limit file and restore the removed lines from the backup (or uncomment
them, and comment out everything else). Repeat the previous step to see if the
program starts to the fail again.
5. Repeat the last two steps, as many times as necessary, to find the minimum
number of methods that must be compiled to trigger the failure. Often, you can
reduce the file to a single line.
When you have obtained a workaround and located the failing method, you can
limit the workaround to the failing method. For example, if the method
java/lang/Math.max(II)I causes the program to fail when compiled with
optLevel=hot, you can run the program with:
-Xjit:{java/lang/Math.max(II)I}(optLevel=warm,count=0)
which tells the JIT to compile only the troublesome method at an optimization
level of ″warm″, but compile all other methods normally.
To see if the JIT is crashing in the middle of a compilation, use the verbose option
with the following additional settings:
-Xjit:verbose={compileStart|compileEnd}
These verbose settings report when the JIT starts to compile a method, and when
it ends. If the JIT fails on a particular method (that is, it starts compiling, but
crashes before it can end), use the exclude= parameter to exclude it from
compilation (refer to “Locating the failing method” on page 238). If excluding the
method prevents the crash, you have an excellent workaround that you can use
while the service team correct your problem.
Also try adjusting the JIT threshold (using trial and error) for short-running
applications to improve performance. Refer to “Selectively disabling the JIT” on
page 237.
240 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 28. Garbage Collector diagnostics
This chapter describes how to diagnose the garbage collection operation. The
topics that are discussed in this chapter are:
v “How does the Garbage Collector work?”
v “Common causes of perceived leaks”
v “Basic diagnostics (-verbosegc)” on page 242
v “Advanced diagnostics” on page 249
v “TGC tracing” on page 250
v “Heap and native memory use by the JVM” on page 254
The IBM Virtual Machine for Java includes a memory manager, which manages the
Java heap. The memory manager allocates space from the heap as objects are
instantiated, keeping a record of where the remaining free space in the heap is
located. When free space in the heap is low and an object allocation cannot be
satisfied, an allocation failure is triggered and a garbage collection cycle is started.
Garbage collection identifies and frees previously allocated storage that is no
longer in use. When this process is complete, the memory manager retries the
allocation that it could not previously satisfy.
An application can request a manual garbage collection at any time, but this action
is not recommended. See “How to coexist with the Garbage Collector” on page 18.
The key here is the condition unreachable. The Garbage Collector traces all
references that an object makes to other objects. Any such reference automatically
means that an object is reachable and not garbage. So, if the objects of an
application make reference to other objects, those other objects are live and cannot
be collected. However, obscure references sometimes exist that the application
overlooks. These references are reported as memory leaks.
Listeners
By installing a listener, you effectively attach your object to a static reference that is
in the listener. Your object cannot be collected while the listener is active. You must
explicitly uninstall a listener when you have finished using the object to which you
attached it.
Hash tables
Anything that is added to a hash table, either directly or indirectly, from an
instance of your object, creates a reference to your object from the hashed object.
Hashed objects cannot be collected unless they are explicitly removed from any
hash table to which they have been added.
Hash tables are common causes of perceived leaks. If an object is placed into a
hash table, that object and all the objects that it references are reachable.
Static data
This exists independently of instances of your object. Anything that it points to
cannot be collected even if no instances of your class are present that contain the
static data.
JNI references
Objects that are passed from the JVM to an application across the JNI interface
have a reference to them that is held in the JNI code of the JVM. Without this
reference, the Garbage Collector cannot trace live native objects. Such references
must be explicitly cleared by the native code application before they can be
collected. See the JNI documentation on the Sun website (java.sun.com) for more
information.
Premature expectation
You instantiate a class, finish with it, tidy up all listeners, and so on. You have a
finalizer in the class, and you use that finalizer to report that the finalizer has been
called. On all the later garbage collection cycles, your finalizer is not called. It
seems that your unused object is not being collected and that a memory leak has
occurred, but this is not so.
The IBM Garbage Collector does not collect garbage unless it needs to. It does not
necessarily collect all garbage when it does run. It might not collect garbage if you
manually invoke it (by using System.gc()). This is because running the Garbage
Collector is an intensive operation, and it is designed to run as infrequently as
possible for as a short time as possible.
242 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Basic diagnostics (-verbosegc)
<sys> Indicates that a System.gc() has occurred. The id attribute gives the
number of this System.gc() call; in this case, this is the first such call in the
life of this VM. timestamp gives the local timestamp when the System.gc()
call was made and intervalms gives the number of milliseconds that have
elapsed since the previous System.gc() call. In this case, because this is the
first such call, the number returned is zero.
<gc type=″global″>
Indicates that, as a result of the System.gc() call, a global garbage collection
was triggered. The contents of the <gc> tag for a global collection are
explained in detail in “Global collections” on page 245.
<time>
Shows the total amount of time taken to handle the System.gc call (in
milliseconds).
Allocation failures
When an attempt is made to allocate to the heap but insufficient memory is
available, an allocation failure is triggered. The output produced depends on the
area of the heap in which the allocation failure occurred.
failure. Note that, following the garbage collection, freespace might drop
by more than this amount, because of a possible freelist discard or TLH
refresh.
<time exclusiveaccessms=>
Shows the amount of time taken to obtain exclusive VM access. Note that a
further optional line <warning details="exclusive access time includes
previous garbage collections" /> might occasionally appear, to inform
you that the following garbage collection was queued because the
allocation failure was triggered while another thread was already
performing a garbage collection. Normally, this first collection will have
freed enough heap space to satisfy both allocation requests (the original
one that triggered the garbage collection and the subsequently queued
allocation request). However, sometimes this is not the case and another
garbage collection is triggered almost immediately. This additional line
informs you that the pause time displayed might be slightly misleading
unless you are aware of the underlying threading used.
<nursery>
Shows the status of the nursery at the time of the failure, including the
percentage that was free.
<gc> Indicates that, as a result of the allocation failure, a garbage collection was
triggered. In this case, a scavenger collection occurred. The contents of this
tag are explained in detail in “Advanced diagnostics” on page 249.
<time>
Shows the total time taken to handle the allocation failure.
<nursery> and <tenured>
Show the status of the different heap areas following the handling of the
allocation failure, including the percentage of each area free.
All the elements of this output have the same meanings as those for an allocation
failure occurring in the nursery. The only difference is the addition of an expansion
tag.
<expansion>
Indicates that during the handling of the allocation (but after the garbage
collection) a heap expansion was triggered. The area expanded, amount the
area was increased by (in bytes), its new size, the time taken to expand,
and the reason for the expansion are shown.
244 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Basic diagnostics (-verbosegc)
Global collections
An example of the output produced when a global collection is triggered is:
<gc type="global" id="6" totalid="6" intervalms="383.226">
<compaction movecount="139926" movebytes="9478888" />
<refs_cleared soft="0" weak="0" phantom="0" />
<finalization objectsqueued="0" />
<timesms mark="33.391" sweep="1.760" compact="65.958" total="101.149" />
<tenured freebytes="1784720" totalbytes="11337472" percent="15" />
</gc>
<gc> Indicates that a garbage collection was triggered on the heap.
Type=″global″ indicates that this was a global collection (mark, sweep,
possibly compact). The id attribute gives the occurrence number of this
global collection. The totalid indicates the total number of garbage
collections (of all types) that have taken place. Currently this is the sum of
the number of global collections and the number of scavenger collections.
intervalms gives the number of milliseconds since the previous global
collection.
<compaction>
Shows the number of objects that were moved during compaction, and the
total number of bytes these objects represented. This line appears only if
compaction occurred during the collection.
<refs_cleared>
Provides information relating to the number of Java reference objects that
were cleared during the collection. In this example, no references were
cleared.
<finalization>
Provides information detailing the number of objects containing finalizers
that were enqueued for VM finalization during the collection. Note that
this is not equal to the number of finalizers that were run during the
collection, because finalizers are scheduled by the VM.
<timems>
Provides information detailing, respectively, times taken for each of the
mark, sweep, and compact phases, as well as the total time taken. When
compaction was not triggered, the number returned is zero. Note that if
the VM being run is not compiled with compaction support, the compact
field will not be displayed.
<tenured>
Indicates the status of the tenured area following the collection. If running
in generational mode, there will also be a <nursery> line output, showing
the status of the active nursery area too.
Scavenger collections
An example of the output produced when a scavenger collection is triggered is:
<gc type="scavenger" id="17" totalid="19" intervalms="145.701">
<failed type="tenured" objectcount="355" bytes="32964" />
<flipped objectcount="4192" bytes="655164" />
<tenured objectcount="3858" bytes="650928" />
<finalization objectsqueued="0" />
<scavenger tiltratio="74" />
<nursery freebytes="1440760" totalbytes="2097152" percent="68" tenureage="1" />
<time totalms="6.451" />
</gc>
<gc> Indicates that a garbage collection has been triggered, and
type=″scavenger″ indicates that this is a scavenger collection. The id
attribute shows the number of this type of collection that have taken place
and the totalid attribute shows the total number of garbage collections of
all types that have taken place (including this one). intervalms gives the
amount of time (in milliseconds) since the last collection of this type.
<failed type=″tenured″>
Indicates that the scavenger failed to tenure some objects when it tried to
during the collection. The number affected and the total bytes represented
by these objects is shown. Additionally or alternatively, <failed
type=″flipped″> could have been displayed, which would indicate that the
scavenger failed to flip certain objects into the survivor space.
<flipped>
Shows the number of objects that were flipped into the survivor space
during the scavenge, together with the total number of bytes flipped.
<scavenger tiltratio=″x″ />
Shows the amount that new-space is tilted by, following the post-scavenge
retilt. The scavenger can redistribute memory between the allocate and
survivor areas to maximize the time between scavenges and the number of
objects that ″die young″.
<tenured>
Shows the number of objects that were moved into the old area during the
scavenge, together with the total number of bytes tenured.
<nursery>
Shows the amount of free and total space in the nursery area following the
scavenge, along with the current number of flips an object must have
survived in order to be tenured.
<time>
Shows the total time taken to perform the scavenge, in milliseconds.
Note that there are a number of additional lines that can be output during a
scavenge. It is possible for a scavenge to fail (for example, if the nursery was
excessively tilted with a full old area, and certain objects could not be copied or
tenured). In this case, an additional <warning details="aborted collection" />
line is displayed.
It is also possible for the entirety of new space to be resized following a scavenge.
Again, this is shown as a separate line of -verbosegc.
Concurrent mark
When running with concurrent mark, there are several additional -verbosegc
outputs which will be displayed.
Concurrent kickoff
When the concurrent mark process is triggered, the following output is produced:
<con event="kickoff" timestamp="Fri Nov 14 15:14:27 2003">
<stats tenurefreebytes="439416" tracetarget="4346357" kickoff="543294" tracerate="8" />
</con>
This output shows that concurrent mark was kicked off, and gives a local
timestamp for this. Statistics are produced showing the amount of free space in the
246 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Basic diagnostics (-verbosegc)
tenured area, the target amount of tracing to be performed by concurrent mark, the
kickoff threshold at which concurrent is triggered, and the initial trace rate. The
trace rate represents the amount of tracing each mutator thread should perform
relative to the amount of space it is attempting to allocate within the heap. In this
example, a mutator thread that allocates 20 bytes will be required to trace 20 * 8 =
160 bytes. If also running in generational mode, an additional nurseryfreebytes=
attribute is displayed, showing the status of the nursery as concurrent mark was
triggered.
248 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Basic diagnostics (-verbosegc)
<stats>
Shows the tracing statistics for the concurrent tracing that has taken place
previously. The target amount of tracing is shown, together with that
which actually took place (both by mutators threads and helper threads).
Information is displayed showing the number of cards in the card table
that were cleaned during the concurrent mark process, and an estimation
of the total number of dirty cards.
<con event=″final card cleaning″>
Shows that final card cleaning has been triggered. The number of cards
cleaned is displayed, together with the number of milliseconds taken to do
so.
This output shows that a system.gc() call was made after concurrent mark had
kicked off. In this case, enough tracing had been performed for the work to be
reused, so concurrent mark is halted rather than aborted. The results for final
card-cleaning are also shown.
Advanced diagnostics
The -verbosegc option is the main diagnostic that is available for runtime analysis
of the Garbage Collector. However, additional command-line options are available
that affect the behavior of the Garbage Collector and might aid diagnostics. These
options are:
-Xdisableexplicitgc
-Xgcthreads
-Xclassgc
-Xnoclassgc
-Xcompactgc
-Xnocompactgc
-Xcompactexplicitgc
-Xnocompactexplicitgc
-Xdisableexplicitgc
This option converts Java application calls to java.lang.System.gc() into no-ops.
-Xgcthreads
This option sets the number of helper threads that the Garbage Collector uses for
parallel operations. The number is set to (number of CPUs − 1). On single CPU
boxes, no helper threads run. The disabling of helper threads disables parallel
operations, at the cost of performance, and might expose problems in this area. No
advantage is gained if you increase the number of threads above the default
setting; you are recommended not to do so.
-Xclassgc
This option enables collection of class objects at every garbage collection.
-Xnoclassgc
This option disables collection of class objects.
-Xcompactgc
This option enables compaction at every garbage collection.
-Xnocompactgc
This option disables heap compaction.
-Xcompactexplicitgc
This option runs full compaction each time System.gc() is called.
-Xnocompactexplicitgc
This option means a compaction is never run when System.gc() is called.
TGC tracing
By enabling one or more TGC (trace garbage collector) traces, more detailed
garbage collection information than that displayed by -verbose:gc will be shown.
This section summarizes the different TGC traces available. The output is piped to
stdout. More than one trace can be enabled simultaneously by separating the
parameters with commas, for example -Xtgc:backtrace,compaction.
-Xtgc:backtrace
This trace shows information tracking which vmThread triggered the garbage
collection. For a System.gc() this might be similar to:
"main" (0x0003691C)
250 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Garbage Collector - TGC tracing
This shows that the GC was triggered by the thread with the name ″main″ and
osThread 0x0003691C.
One line is printed for each global or scavenger collection, showing the thread that
triggered the GC.
-Xtgc:compaction
This trace shows information relating to compaction, similar to:
Compact(3): reason = 7 (forced compaction)
Compact(3): Thread 0, setup stage: 8 ms.
Compact(3): Thread 0, move stage: handled 42842 objects in 13 ms, bytes moved 2258028.
Compact(3): Thread 0, fixup stage: handled 0 objects in 0 ms, root fixup time 1 ms.
Compact(3): Thread 1, setup stage: 0 ms.
Compact(3): Thread 1, move stage: handled 35011 objects in 8 ms, bytes moved 2178352.
Compact(3): Thread 1, fixup stage: handled 74246 objects in 13 ms, root fixup time 0 ms.
Compact(3): Thread 2, setup stage: 0 ms.
Compact(3): Thread 2, move stage: handled 44795 objects in 32 ms, bytes moved 2324172.
Compact(3): Thread 2, fixup stage: handled 6099 objects in 1 ms, root fixup time 0 ms.
Compact(3): Thread 3, setup stage: 8 ms.
Compact(3): Thread 3, move stage: handled 0 objects in 0 ms, bytes moved 0.
Compact(3): Thread 3, fixup stage: handled 44797 objects in 7 ms, root fixup time 0 ms.
This trace shows that compaction occurred during the third global GC, for reason
″7″. The compaction reasons are explained in detail in “Compaction phase” on
page 8. In this case, four threads are performing compaction. The trace shows the
work performed by each thread during setup, move, and fixup. The time for each
stage is shown together with the number of objects handled by each thread.
-Xtgc:concurrent
This trace displays basic extra information about the concurrent mark helper
thread.
<CONCURRENT GC BK thread 0x0002645F activated after GC(5)>
This trace shows when the background thread was activated, and the amount of
tracing it performed (in bytes).
-Xtgc:dump
This trace shows extra information following the sweep phase of a global garbage
collection. This is an extremely large trace – a sample of one GC’s output is:
<GC(4) 13F9FE44 freelen=x000002C4 -- x00000038 spec/jbb/Stock>
<GC(4) 13FA0140 freelen=x00000010>
<GC(4) 13FA0150 freelen=x00000050 -- x0000001C java/lang/String>
<GC(4) 13FA0410 freelen=x000002C4 -- x00000024 spec/jbb/infra/Collections/longBTreeNode>
<GC(4) 13FA0788 freelen=x00000004 -- x00000050 java/lang/Object[]>
<GC(4) 13FA0864 freelen=x00000010>
<GC(4) 13FA0874 freelen=x0000005C -- x0000001C java/lang/String>
<GC(4) 13FA0B4C freelen=x000002C4 -- x00000038 spec/jbb/Stock>
<GC(4) 13FA0E48 freelen=x00000010>
<GC(4) 13FA0E58 freelen=x00000068 -- x0000001C java/lang/String>
<GC(4) 13FA1148 freelen=x000002C4 -- x00000038 spec/jbb/Stock>
<GC(4) 13FA1444 freelen=x00000010>
<GC(4) 13FA1454 freelen=x0000006C -- x0000001C java/lang/String>
<GC(4) 13FA174C freelen=x000002C4 -- x00000038 spec/jbb/Stock>
<GC(4) 13FA1A48 freelen=x00000010>
<GC(4) 13FA1A58 freelen=x00000054 -- x0000001C java/lang/String>
<GC(4) 13FA1D20 freelen=x000002C4 -- x00000038 spec/jbb/Stock>
<GC(4) 13FA201C freelen=x00000010>
A line of output is printed for every free chunk in the system, including dark
matter (free chunks that are not on the free list for some reason, usually because
they are too small). Each line contains the base address and the size in bytes of the
chunk. If the chunk is followed in the heap by an object, the size and class name of
the object is also printed.
| -Xtgc:excessiveGC
| This trace shows statistics for garbage collection cycles.
| This trace shows how much time was spent performing garbage collection and
| how much time was spent out of garbage collection. In this example, garbage
| collection cycle 10 took 122.269 ms to complete and 1.721 ms passed between
| collections 9 and 10. These statistics show that garbage collection accounted for
| 98.61% of the time from the end of collection 9 to the end of collection 10. The
| average time spent in garbage collection is 37.89%.
| When the average time in garbage collection reaches 95%, extra trace entries are
| produced:
| excessiveGC: gcid="65" percentreclaimed="1.70" freedelta="285728" \
| activesize="16777216" currentsize="16777216" maxiumumsize="16777216"
| This trace shows how much garbage was collected. In this example, 285728 bytes
| were reclaimed by garbage collection 65, which accounts for 1.7% of the total heap
| size. The example also shows that the heap has expanded to its maximum size (see
| -Xmx in “General Garbage Collection options” on page 334).
| When the average time in garbage collection reaches 95% and the percentage of
| free space reclaimed by a collection drops below 3%, another trace entry is
| produced:
| excessiveGC: gcid="65" percentreclaimed="1.70" minimum="3.00" excessive gc raised
-Xtgc:freelist
Before a garbage collection, this trace prints information about the free list and
allocation statistics since the last GC. It prints the number of items on the free list,
including ″deferred″ entries (with the scavenger, the unused semispace is a
deferred free list entry). For TLH and non-TLH allocations, this prints the total
number of allocations, the average allocation size, and the total number of bytes
252 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Garbage Collector - TGC tracing
-Xtgc:parallel
This trace shows statistics about the activity of the parallel threads during the
mark and sweep phases of a global GC.
Mark: busy stall tail acquire release
0: 30 30 0 0 3
1: 53 7 0 91 94
2: 29 31 0 37 37
3: 37 24 0 243 237
Sweep: busy idle sections 127 merge 0
0: 10 0 96
1: 8 1 0
2: 8 1 31
3: 8 1 0
This trace shows four threads (0-3) and the work done by each. For mark, the time
spent busy, stalled, and in tail is shown (in milliseconds) together with the number
of work packets each thread acquired and released during marking. For sweep, the
time spent busy and idle is shown (in milliseconds) together with the number of
sweep chunks processed by each thread and in total (127 above). The total merge
time is also shown (0ms above).
-Xtgc:references
This trace shows activity relating to reference handling during garbage collections.
enqueuing ref sun/misc/SoftCache$ValueCell@0x1564b5ac -> 0x1564b4c8
enqueuing ref sun/misc/SoftCache$ValueCell@0x1564b988 -> 0x1564b880
enqueuing ref sun/misc/SoftCache$ValueCell@0x15645578 -> 0x15645434
This trace shows three reference objects being enqueued. The location of the
reference object and the referent is displayed, along with the class name of the
object. Note that for finalizer objects this does not mean the finalizer has been run,
merely that it has been queued to the finalizer thread.
-Xtgc:scavenger
This trace prints a histogram following each scavenger collection. A graph is
shown of the different classes of objects remaining in the survivor space, together
with the number of occurrences of each class and the age of each object (the
number of times it has been flipped). A sample of the output from a single
scavenge is shown below:
{SCAV: tgcScavenger OBJECT HISTOGRAM}
{SCAV: java/io/OutputStreamWriter 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0
{SCAV: java/io/PrintStream 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0
{SCAV: java/io/BufferedInputStream 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
{SCAV: java/lang/Thread[] 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0
{SCAV: java/lang/ThreadGroup[] 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0
{SCAV: sun/io/ByteToCharCp1252 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
{SCAV: sun/io/CharToByteCp1252 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
-Xtgc:terse
This trace dumps the contents of the entire heap before and after a garbage
collection. As such, this is an extremely large trace. For each object or free chunk in
the heap, a line of trace output is produced. Each line contains the base address,
″a″ if it is an allocated object and ″f″ if it is a free chunk, the size of the chunk in
bytes, and if it is an object, its class name. A sample is shown below:
*DH(1)* 230AD778 a x0000001C java/lang/String
*DH(1)* 230AD794 a x00000048 char[]
*DH(1)* 230AD7DC a x00000018 java/lang/StringBuffer
*DH(1)* 230AD7F4 a x00000030 char[]
*DH(1)* 230AD824 a x00000054 char[]
*DH(1)* 230AD878 a x0000001C java/lang/String
*DH(1)* 230AD894 a x00000018 java/util/HashMapEntry
*DH(1)* 230AD8AC a x0000004C char[]
*DH(1)* 230AD8F8 a x0000001C java/lang/String
*DH(1)* 230AD914 a x0000004C char[]
*DH(1)* 230AD960 a x00000018 char[]
*DH(1)* 230AD978 a x0000001C java/lang/String
*DH(1)* 230AD994 a x00000018 char[]
*DH(1)* 230AD9AC a x00000018 java/lang/StringBuffer
*DH(1)* 230AD9C4 a x00000030 char[]
*DH(1)* 230AD9F4 a x00000054 char[]
*DH(1)* 230ADA48 a x0000001C java/lang/String
*DH(1)* 230ADA64 a x00000018 java/util/HashMapEntry
*DH(1)* 230ADA7C a x00000050 char[]
*DH(1)* 230ADACC a x0000001C java/lang/String
*DH(1)* 230ADAE8 a x00000050 char[]
*DH(1)* 230ADB38 a x00000018 char[]
*DH(1)* 230ADB50 a x0000001C java/lang/String
*DH(1)* 230ADB6C a x00000018 char[]
*DH(1)* 230ADB84 a x00000018 java/lang/StringBuffer
*DH(1)* 230ADB9C a x00000030 char[]
*DH(1)* 230ADBCC a x00000054 char[]
*DH(1)* 230ADC20 a x0000001C java/lang/String
*DH(1)* 230ADC3C a x00000018 java/util/HashMapEntry
*DH(1)* 230ADC54 a x0000004C char[]
The JVM does use native memory, but, for efficiency, does not use standard stack
frames. The JIT (see Chapter 4, “Understanding the JIT,” on page 29), the MMI (see
Chapter 27, “JIT problem determination,” on page 237), and the JVM all have their
own styles of stack frames. The only tool that can walk the stack is the dump
formatter (see Chapter 26, “Using the dump formatter,” on page 223). The only
other users of native memory are native code and some types of large native
objects.
254 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Garbage Collector - heap and native memory use by the JVM
Native code
The term “native code ” refers to native code (usually C or C++) that is compiled
into a library and accessed through the JNI. Alternatively, native code can load an
encapsulated JVM. Either way, the native code uses standard OS stack frames,
unless it manages the stack itself. The JVM keeps track of the portion of the stack
that it uses, because it needs this information to find a set of root objects for
garbage collection.
The JVM has no knowledge of and cannot control the native stack in this scenario.
Growth of the native stack is not normally due to JVM code.
256 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 29. Class-loader diagnostics
This chapter describes some diagnostics that are available for class-loading. The
topics that are discussed in this chapter are:
v “Class-loader command-line options”
v “Class-loader runtime diagnostics”
v “Loading from native code” on page 258
For example:
C:\j9test>java -Dibm.cl.verbose=HelloWorld HelloWorld
The sequence of the loaders output is due to the ″delegate first″ convention of the
class loaders. In this convention, each loader checks its cache, then delegates to its
parent loader. Then, if the parent returns null, the loader checks the file system or
equivalent. This is the part of the process that is reported in the example above. In
the command-line definition, the classname can be given as any Java regular
expression. ″Dic*″ will produce output on all classes whose names begin with the
letters ″Dic″, and so on.
258 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 30. Tracing Java applications and the JVM
JVM Trace is a low-overhead trace facility that is provided in all IBM-supplied
JVMs. In most cases, the trace data is kept in compact binary format, with
variable-length trace records from 8 to 64 KB. A cross-platform Java formatter is
supplied to format the trace. You can enable tracepoints at runtime by using levels,
components, group names, or individual tracepoint identifiers.
The trace tool provides an extremely powerful ability to diagnose the JVM.
Tracing methods
You can trace entry to and exit from methods for selected classes. Using the
methods trace option, you can select method trace by class, method name, or both.
Wildcards can be used, and a not operator is provided to allow for complex
selection criteria. Note that this option selects only the methods that are to be
traced. The MT trace component must be selected for a given trace destination. For
example:
-Xtrace:methods={*.*,!java/lang/*.*},print=mt
This routes method trace to stderr for all methods and for all classes except those
that start with java/lang.
Tracing applications
JVM trace contains an application trace facility that allows tracepoints to be placed
in Java code to provide trace data that will be combined with the other forms of
trace. API in the com.ibm.jvm.Trace class is provided to register a Java application
for trace and later to make trace entries. You can control the tracepoints at startup
or enable them dynamically by using Java or C API. When trace is not enabled,
little overhead is caused. Note that an instrumented Java application runs only on
an IBM-supplied JVM.
Internal trace
The IBM Virtual Machine for Java is extensively instrumented for trace, as
described in this chapter. Interpretation of this trace data requires knowledge of the
internal operation of the JVM, and is provided for support personnel who
diagnose JVM problems.
Note: No guarantee is given that tracepoints will not vary from release to release
and from platform to platform.
Note: On some computers, power management affects the timers that trace uses,
and gives misleading information. This problem affects mainly Intel-based
mobiles, but it can occur on other architectures. For reliable timing
information, disable power management.
To examine the trace data, you must snap or dump, then format the buffers.
Snapping buffers
Buffers are snapped when:
v An uncaught Java exception occurs
v An operating system signal or exception occurs
v The com/ibm/jvm/Trace.snap() Java API is called
v The JVMRI TraceSnap function is called
The resulting snap file is placed into the current working directory with a name of
the format Snapnnnn.yyyymmdd.hhmmssth.process.trc, where nnnn is a sequence
number starting at 0001 (at JVM startup), yyyymmdd is the current date, hhmmssth
is the current time, and process is the process identifier.
Dumping buffers
You can also dump the buffers by using the operating system dump services. You
can then extract the buffers from the dump by using the Dump Viewer.
260 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Where does the data go?
A thread is never stopped to allow trace buffers to be written. If the rate of trace
data generation greatly exceeds the speed of the output device, excessive memory
usage might occur and cause out-of-memory conditions. To prevent this, use the
nodynamic option of the buffers trace option. For long running trace runs, a wrap
option is available to limit the file to a given size. See the output option for details.
You must use the trace formatter to format trace data from the file.
Note: Because of the buffering of trace data, if the normal JVM termination is not
performed, residual trace buffers might not be flushed to the file. Snap
dumps do not occur, and the trace bytes are not flushed except when a fatal
operating-system signal is received. The buffers can, however, be extracted
from a system dump if that is available.
External tracing
You can route trace to an agent by using JVMRI TraceRegister. This allows a
callback routine to be invoked when any of the selected tracepoints is found in real
time; that is, no buffering is done. The trace data is in raw binary form.
Tracing to stderr
For lower volume or non-performance-critical tracing, the trace data can be
formatted and routed to stderr in real time. See Chapter 25, “Using method trace,”
on page 219.
Trace combinations
Most trace destinations can be combined, with the same or different trace data
going to different destinations. The exception to this is in-storage trace and trace to
a file, which are mutually exclusive.
Note that this only applies to options specified on the command-line - not those
specified in a properties file.
The syntax for specifying trace options depends on the launcher. Usually, it is:
java -Xtrace:<name>,<another_name>=<value> HelloWorld
When you use the IBM_JAVA_OPTIONS environment variable, use this syntax:
set IBM_JAVA_OPTIONS=-Xtrace:<name>,<another_name>=<value>
or
export IBM_JAVA_OPTIONS=-Xtrace:<name>,<another_name>=<value>
These properties have equivalents in the Java and JVMRI API that was mentioned
earlier.
262 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
Note: An existing restriction means that properties that take the form
<name>=<value> cannot be left to default if they are specified in the
property file; that is, you must specify a value, for example maximal=all.
Examples:
Use IBMTRACE.properties in the current directory:
-Xtrace:properties
Use trace.prop in the current directory:
-Xtrace:properties=trace.prop
Use c:\trc\gc\trace.props:
-Xtrace:properties=c:\trc\gc\trace.props
264 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
minimal=all
// maximal=st
maximal=cl
buffers=20k
output=c:\traces\classloader.trc
print=tpid(4002,4005)
buffers=nnnk|nnnm[,dynamic|nodynamic]
This option specifies the size of the buffer as nnn KB or MB. This buffer is
allocated for each thread that makes trace entries. If external trace is enabled,
this value is doubled; that is, each thread allocates two or more buffers. The
same buffer size is used for state and exception tracing, but, in this case,
buffers are allocated globally. The default is 8 KB per thread.
The dynamic and nodynamic options have meaning only when tracing to an
output file. If dynamic is specified, buffers are allocated as needed to match
the rate of trace data generation to the output media. Conversely, if nodynamic
is specified, a maximum of two buffers per thread is allocated. The default is
dynamic. The dynamic option is effective only when you are tracing to an
output file.
Important: If nodynamic is specified, you might lose trace data if the volume
of trace data that is produced exceeds the bandwidth of the trace
output file. Message UTE115 is issued when the first trace entry is
lost, and message UTE018 is issued at JVM termination.
Examples:
Dynamic buffering with 8 KB buffers:
-Xtrace:buffers=8k
or in a properties file:
buffers=8k
or in a properties file:
buffers=2m
or in a properties file:
buffers=128k,nodynamic
applids=application_name[,...]
This option prepares for trace to be enabled for one or more Java applications
that have been instrumented for application trace. The identifier
application_name must match the name under which the application will
register itself. This name can later be used as a component name for tracepoint
selection.
minimal[=[[!]tracepoint_specification[,...]],
maximal[=[[!]tracepoint_specification[,...]], count[=[[!]tracepoint_specification[,...]],
print[=[[!]tracepoint_specification[,...]], iprint[=[[!]tracepoint_specification[,...]],
exception[=[[!]tracepoint_specification[,...]],
external[=[[!]tracepoint_specification[,...]]
Summary
These options control which individual tracepoints are activated at runtime
and the implicit destination of the trace data. Minimal and maximal trace data
is placed into internal trace buffers that can then be written to a snap file or
written to the files that are specified in an output trace option.
Tracepoints that are activated with count are only counted. The totals are
written to dgTrcCounters in the current directory at JVM termination.
Tracepoints that are activated with print or iprint are routed to stderr.
When exception trace is enabled, the trace data is collected in internal buffers
that are separate from the normal buffers. These internal buffers can then be
written to a snap file or written to the file that is specified in an
exception.output system property.
External trace data is passed to a registered trace listener. Note that all these
properties are independent of each other and can be mixed and matched in
any way that you choose.
Multiple statements of each type of trace are allowed and their effect is
cumulative. Of course, you would have to use a trace properties file for
multiple trace options of the same name.
See “state.output” on page 271 for information about state trace, which is
enabled in a different way, independently of these options.
Types of trace
The minimal option records only the timestamp and tracepoint identifier.
When the trace is formatted, missing trace data is replaced with the characters
″???″ in the output file. The maximal option specifies that all associated data is
traced. If a tracepoint is activated by both trace options, maximal trace data is
produced. Note that these types of trace are completely independent from any
types that follow them. For example, if the minimal option is specified, it does
not affect a later option such as print.
The count option requests that a count of the selected tracepoints is kept. At
JVM termination, all non-zero totals of tracepoints (sorted by tracepoint id) are
written to a file, called utTrcCounters, in the current directory. This information
is useful if you want to determine the overhead of particular tracepoints, but
do not want to produce a large amount (GB) of trace data.
The print option causes the specified tracepoints to be routed to stderr in
real-time. The tracepoints are formatted by J9TraceFormat.dat, which must be
available at runtime. TraceFormat.dat is shipped in sdk/jre/lib and is
automatically found by the runtime.
The exception option allows low-volume tracing in buffers and files that are
distinct from the higher-volume information that minimal and maximal
tracing have provided. In most cases, this information is exception-type data,
but you can use this option to capture any trace data that you want.
This form of tracing is channeled through a single set of buffers, as opposed to
the buffer-per-thread approach for normal trace, and buffer contention might
occur if high volumes of trace data are collected. A difference exists in the
tracepoint_specification defaults for exception tracing; see “Tracepoint
selection” on page 267.
Note: When exception trace is entered for an active tracepoint, the current
thread id is checked against the previous caller’s thread id. If it is a
266 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
Note: Some tracepoints can be both an exit and an exception; that is, the
function ended with an error. If you specify either exit or exception,
these tracepoints will be included.
Examples:
All tracepoints:
-Xtrace:maximal
All tracepoints except j9vrb and j9trc:
-Xtrace:minimal={all,!j9vrb,!j9trc}
All entry and exit tracepoints in j9bcu:
-Xtrace:maximal={j9bcu(entry,exit)}
All tracepoints in j9mm except 4000, 4001, 4002, 4003:
-Xtrace:maximal={j9mm,!tpid(4000,4001,4002,4003)}
Tracepoints 18005 through 1801f and c003:
-Xtrace:print={tpid(18005-1801f,c003)}
All j9trc tracepoints:
-Xtrace:count=j9trc
All entry and exit tracepoints:
-Xtrace:external={all(entry,exit)}
All exception tracepoints:
-Xtrace:exception
All exception tracepoints:
-Xtrace:exception=all(exception)
All exception tracepoints in j9bcu:
-Xtrace:exception=j9bcu
Tracepoints c03e through c113:
-Xtrace:exception=tpid(c03e-c113)
Trace levels
Tracepoints have been assigned levels 0 through 9 that are based on the
importance of the tracepoint. A level 0 tracepoint is very important and is
reserved for extraordinary events and errors; a level 9 tracepoint is in-depth
component detail. To specify a given level of tracing, the level0 through level9
keywords are used. You can abbreviate these keywords to l0 through l9. For
example, if level5 is selected, all tracepoints that have levels 0 through 5 are
included. Level specifications do not apply to explicit tracepoint specifications
that use the TPID keyword.
You can use these keywords either before the tracepoint selection, or as a type
modifier. When a keyword is used before a tracepoint selection, that keyword
applies to all tracepoint selection criteria that follow it in the trace option. For
example:
-Xtrace:maximal={level5,j9mm,j9trc,j9bcu,level1,all}
or
-Xtrace:maximal={l5,j9mm,j9trc,j9bcu,l1,all}
In this example, tracepoints that have a level of 5 or below are enabled for the
j9mm, j9trc, and j9bcu components. Tracepoints that have a level of 1 or below
are enabled for all the other components. Note that the level applies only to
the current statement, so if multiple trace selection statements appear in a trace
properties file, the level is reset to the default for each new statement.
Alternatively, you can specify levels as a type modifier. In this case, the level
applies only to the component with which it is associated. The following
example is functionally equivalent to the global example that is shown above:
-Xtrace:maximal={j9mm(level5),j9trc(level5),j9bcu(level5),all(level1)}
268 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
or
-Xtrace:maximal={j9mm(l5),j9trc(l5),j9bcu(l5),all(l1)}
When the not operator is specified, the level is inverted; that is, !j9mm(level5)
disables all tracepoints of level 6 or above for the j9mm component. For
example:
-Xtrace:print={all,!j9trc(l5),!j9mm(l6)}
enables trace for all components at level 9 (the default), but disables level 6
and above for the locking component, and level 7 and above for the storage
component.
Examples:
Count all level zero and one tracepoints hit:
-Xtrace:count=all(l1)
Produce maximal trace of all components at level 5 and j9mm at level 9:
-Xtrace:maximal={LeVeL5,all,j9mm(L9)}
Trace all components at level 6, but do not trace j9vrb at all, and do not
trace level 0 through 3 entry and exit tracepoints in the j9trc component:
-Xtrace:minimal={all(l6),!j9vrb,!j9trc(level3,entry,exit)}
methods=method_specification[,...]
This trace option identifies which classes and methods are to be prepared to be
traced. You can then trace these methods by selecting the MT component
though the normal trace selection mechanism. When more than one
specification is made, it is cumulative, as if processed from left to right.
Although method trace works with the JIT on, input parameters cannot be
traced if the JIT is active.
Important: This trace option selects only the methods that are to be traced.
You must use one of the trace selection properties to select the
tracepoints that are in the MT component.
The method_specification is:
v [!][*]class[*][.[*]method[*]][()], where
! is a logical not. That is, the class or methods that are specified
immediately following the ! are deselected for method trace.
* is a wildcard that can appear at the beginning, end, or both, of the
class and method names.
class is the package or class name. Note that the delimiter between parts of
the package name is a forward slash, ’/’, even on platforms like
Windows that use a backward slash as a path delimiter.
. is the delimiter between the class and method.
method is the method name.
Examples:
Select all methods for all classes and print them with indentation:
-Xtrace:methods=*,iprint=mt
All methods that are in java/lang/String. The trace data will be placed in
internal buffers:
-Xtrace:methods=java/lang/String.*,maximal=mt
All methods that contain a ″y″ in classes that start with com/ibm and print
them:
-Xtrace:methods=com/ibm*.*y*,print=mt
All methods that contain a ″y″ and do not start with an ″n″ in classes that
start with com/ibm and print them:
-Xtrace:methods={com/ibm*.*y*,!n*},iprint=mt
output=trace_filespec[,nnnm[,generations]]
This trace options indicates that minimal, or maximal trace data, or both, must
be sent to trace_filespec. If the file does not already exist, it is created
automatically. If it does already exist, it is overwritten.
Optionally:
v You can limit the file to nnn MB, at which point it wraps nondestructively to
the beginning. If you do not limit the file, it grows until all disk space has
been used.
v If you want the final trace filename to contain today’s date, the PID number
that produced the trace, or the time, do one of the following steps as
appropriate (see also the examples at the end of this section).
– To include today’s date (in ″yyyymmdd″ format) in the trace filename,
specify ″%d″ as part of the trace_filespec.
– To include the pidnumber of the process that is generating the tracefile,
specify ″%p″ as part of the trace_filespec.
– To include the time (in 24-hour hhmmss format) in the trace filename,
specify ″%t″ as part of the trace_filespec.
v You can specify generations as a value 2 through 36. These values cause up
to 36 files to be used in a round-robin way when each file reaches its size
threshold. When a file needs to be reused, it is overwritten. Therefore, if x
generations of n MB files are specified, the worst case is that only ((x - 1) * n
÷ x ) MB of trace data might be available. If generations is specified, the
filename must contain a ″#″ (hash, pound symbol), which will be substituted
with its generation identifier, the sequence of which is 0 through 9 followed
by A through Z.
Note: When tracing to a file, buffers for each thread are written when the
buffer is full or when the JVM terminates. If a thread has been inactive
for a period of time before JVM termination, what seems to be ’old’
trace data is written to the file. When formatted, it then seems that trace
data is missing from the other threads, but this is an unavoidable
side-effect of the buffer-per-thread design. This effect becomes especially
noticeable when you use the generation facility, and format individual
earlier generations.
Examples:
Trace output goes to /u/traces/gc.problem; no size limit:
-Xtrace:output=/u/traces/gc.problem
Output goes to trace and will wrap at 2 MB:
-Xtrace:output={trace,2m}
Output goes to gc0.trc, gc1.trc, gc2.trc, each 10 MB in size:
-Xtrace:output={gc#.trc,10m,3}
270 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
Examples:
Trace output goes to /u/traces/exception.trc. No size limit:
-Xtrace:exception.output=/u/traces/exception.trc
Output goes to except and wraps at 2 MB:
-Xtrace:exception.output={except,2m}
Output filename contains today’s date in yyyymmdd format (for example,
traceout.20041025.trc):
-Xtrace:exception.output=traceout.%d.trc
Output file contains the number of the process (the PID number) that
generated it (for example, tracefrompid2112.trc):
-Xtrace:exception.output=tracefrompid%p.trc
Output filename contains the time in hhmmss format (for example,
traceout.080312.trc):
-Xtrace:exception.output=traceout.%t.trc
state.output=state_trace_filespec[,nnnm]
This trace option indicates that “state” information should be captured in
state_trace_filespec. The state trace captures information about the JVM that
could be useful later, when the normal trace files or internal buffers have
wrapped many times.
Examples of state data might be:
v Interned string values and ids
v Classblock address or name correlation
v Methodblock address or name correlation
State trace differs from other forms of trace in that it is either totally on or off.
You cannot control which individual tracepoints are enabled at runtime. By
specifying this trace option, you turn it on. If state_trace_filespec does not
already exist, it is created automatically. If it does already exist, it is
overwritten. If nnn is not specified, the size of the file is not limited. If nnn is
specified, two files are created. The first file is named state_file_filespec with a
0 (zero) suffix and contains up to nnn MB of state information that is never
lost; that is, it never wraps. The second file is named state_file_filespec with a
1 (one) suffix and contains up to nnn MB of state information that wraps; that
is, state information might be lost. State trace captures all the startup state
information and all the latest state information. The file 0 and 1 filename
qualifiers position can optionally be controlled by the inclusion of a # (hash or
pound sign) in the filename; the # will be replaced by 0 or 1 respectively.
Under normal conditions, nnn should not be specified, but in the case of
long-running JVMs, its use might be unavoidable to limit the file size. In this
case, some useful state data could be lost.
Optionally, if you want the final trace filename to contain today’s date, the PID
number that produced the trace, or the time, do one of the following steps as
appropriate (see also the examples at the end of this section).
v To include today’s date (in ″yyyymmdd″ format) in the trace filename,
specify ″%d″ as part of the state_trace_filespec.
v To include the pidnumber of the process that is generating the tracefile,
specify ″%p″ as part of the state_trace_filespec.
v To include the time (in 24-hour hhmmss format) in the trace filename,
specify ″%t″ as part of the state_trace_filespec.
Examples:
Trace output goes to /u/traces/state; no size limit:
-Xtrace:state.output=/u/traces/state
Output goes to state0 for 4 MB, then state1, wrapping at 4 MB:
-Xtrace:output={state,4m}
Output goes to state0.trc for 4 MB, then state1.trc:
-Xtrace:state.output={state#.trc,4m}
Output filename contains today’s date in yyyymmdd format (for example,
traceout.20041025.trc):
-Xtrace:state.output=traceout.%d.trc
Output file contains the number of the process (the PID number) that
generated it (for example, tracefrompid2112.trc):
-Xtrace:state.output=tracefrompid%p.trc
Output filename contains the time in hhmmss format (for example,
traceout.080312.trc):
-Xtrace:state.output=traceout.%t.trc
suspend
Suspends tracing globally (for all threads and all forms of tracing) but leaves
tracepoints activated.
Example:
272 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
Tracing suspended:
-Xtrace:suspend
resume
Resumes tracing globally. Note that suspend and resume are not recursive.
That is, two suspends that are followed by a single resume cause trace to be
resumed.
Example: Trace resumed (not much use as a startup option):
-Xtrace:resume
suspendcount=<count>
This trace option is for use with the trigger option (see “trigger”).
This suspendcount=<count> trace option determines whether tracing is
enabled for each thread. If <count> is greater than zero, each thread initially
has its tracing enabled and must receive <count> suspend this action before it
stops tracing.
Note: You cannot use resumecount and suspendcount together because they
both set the same internal counter.
Example:
Start with all tracing turned on. Each thread stops tracing when it has had
three suspendthis actions performed on it:
-Xtrace:suspendcount=3
resumecount=count
This system property is for use with the trigger property (see “trigger”).
This resumecount=<count> system property determines whether tracing is
enabled for each thread. If <count> is greater than zero, each thread initially
has its tracing disabled and must receive <count> resume this action before it
starts tracing.
Note: You cannot use resumecount and suspendcount together because they
both set the same internal counter.
Example:
Start with all tracing turned off. Each thread starts tracing when it has had
three resumethis actions performed on it:
-Xtrace:resumecount=3
trigger=clause[,clause][,clause]...
This trace option determines when various triggered trace actions should
occur. Supported actions include turning tracing on and off for all threads,
turning tracing on or off for the current thread, or producing a variety of
dumps.
Note: This trace option does not control what is traced. It controls only
whether what has been selected by the other trace options is produced
as normal or is blocked.
Each clause of the trigger option can be tpid(...), method(...), group(...), or
threshold(). You can specify multiple clauses of the same type if required, but
you do not need to specify all types. The clause types are:
method(methodspec,[entryAction],[exitAction][,delayCount][,matchcount])
On entering a method that matches methodspec, perform the specified
Actions:
Wherever an action must be specified, you must select from the following
choices:
suspend
Suspend ALL tracing (except for special trace points).
resume
Resume ALL tracing (except for threads that are suspended by the
action of the resumecount property and Trace.suspendThis() calls).
suspendthis
Increment the suspend count for this thread. If the suspend-count is
greater than zero, all tracing for this thread is prevented.
resumethis
Decrement the suspend count for this thread. If the suspend-count is
zero or below, tracing for this thread is resumed.
coredump (or sysdymp)
Produce a coredump.
javadump
Produce a javadump or javacore.
heapdump
Produce a heap dump (see Chapter 22, “Using Heapdump,” on page
205).
snap Snap all active trace buffers to a file in the current working directory.
The name of the file is in the format
Snapnnnn.yyyymmdd.hhmmssth.ppppp.trc, where nnnn is the sequence
number of the snap file since JVM startup, yyyymmdd is the date,
hhmmssth is the time, and ppppp is the process id in decimal with
leading zeroes removed.
abort Halt the execution of the JVM.
segv Cause a segmentation violation. (Intended for use in debugging.)
Examples:
274 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
v Start tracing this thread when it enters any method in java/lang/String and
stop tracing when it leaves it:
-Xtrace:resumecount=1
-Xtrace:trigger={method(java/lang/String.*,resumethis,suspendthis)}
v Resume all tracing when any thread enters a method in any class that starts
with “error”:
-Xtrace:trigger={method(*.error*,resume)}
v When you reach the 1000th and 1001st tracepoint from the ″jvmri″ trace
group, produce a core dump.
Note: Without matchcount there would be a risk of filling your disk with
coredump files.
-Xtrace:trigger={group(staticmethods,coredump,1000,2)}
What to trace
JVM trace can produce large amounts of data in a very short time. Before running
trace, think carefully about what information you need to solve the problem. In
many cases, you need only the trace information that is produced shortly before
the problem occurs; you should consider using the wrap option. Also, in many
cases, it is enough to use internal trace with an increased buffer size and snap the
trace when the problem occurs. If the problem results in a thread stack dump or
operating system signal or exception, trace buffers are snapped automatically to a
file that is in the current directory. The file is called:
Snapnnnn.yyyymmdd.hhmmssth.process.trc.
You must also think carefully about which components need to be traced and what
level of tracing is required. For example, if you are tracing a suspected garbage
collection problem, it might be enough to trace all components at level 1 or 3, and
ST at level 9, while maximal can be used to show parameters and other
information for the failing component.
Following the version number is a component name, followed by a line for each
tracepoint defined in that component, the format of which for this JVM is: nnnnnn
t o l e symbolic_name ″tracepoint_formatting_template″ where nnnnnn is the hex
tracepoint ID, t is the tracepoint type (0 through 11), o is the overhead (0 through
10) , l is the level of the tracepoint (0 through 9, or - if the tracepoint is obsolete) , e
is the explicit setting flag (Y/N), symbolic_name is the name of the tracepoint,
tracepoint_formatting_template is the template used to format the entry.
276 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
Note that this is subject to change without notice, but the version number will be
different.
Application trace
Application trace allows you to trace Java applications using the JVM Trace
Facility.
You must register your Java application with application trace and add trace calls
where appropriate. When you run your application, the trace calls are treated as
no-operations. Unless you specified application trace at startup, the overhead is
very low. If you have started application trace, you can enable or disable
individual tracepoints at any time.
Note: If you are running your application with application trace or do not specify
the -Xtrace option, you might see the following error message:
JVMJ9VM034E jvmri requires trace engine: run with -Xtrace flag
You can either ignore this message or prevent it by using the -Xtrace option.
The registerApplication() method returns an integer that you must use on further
trace() calls. If tracing of the application is enabled, the integer returned is positive;
otherwise, it is -1.
Tracepoints
The following trace methods are implemented:
278 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
import com.ibm.jvm.Trace;
public class HelloWorld
{
static int handle;
static String[] templates;
public static void main (String[] args)
{
templates = new String[8];
templates[0] = Trace.ENTRY + "Entering %s";
templates[1] = Trace.EXIT + "Exiting %s";
templates[2] = Trace.EVENT + "Event id %d, text = %s";
templates[3] = Trace.EXCEPTION + "Exception: %s";
templates[4] = Trace.EXCEPTION_EXIT + "Exception exit from %s";
You can obtain a similar result by specifying iprint on the command line:
java -Xtrace:applids=HelloWorld, iprint=HelloWorld HelloWorld
Printf specifiers
Application trace supports the ANSI C printf specifiers. You must be careful when
you select the specifier; otherwise you might get unpredictable results, including
abnormal termination of the JVM.
For 64-bit integers, you must use the ll (lower case LL, meaning long long)
modifier. For example: %lld or %lli.
For pointer-sized integers use the z modifier. For example: %zx or %zd.
The syntax is the same as that used in a trace properties file for the print, iprint,
count, maximal, minimal and external trace options.
void snap();
This method causes all active trace buffers to be written to a unique filename. You
must have activated trace previously with the maximal or minimal options and
without the out option.
void suspend();
The Trace.suspend() method suspends tracing for all the threads in the JVM. It is
not recursive.
void resume();
The Trace.resume() method resumes tracing for all threads in the JVM. It is not
recursive.
void suspendThis();
The Trace.suspendThis() method decrements the suspend and resume count for the
current thread and suspends tracing the thread if the result is negative.
void resumeThis();
280 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Controlling the trace
The Trace.resumeThis() method increments the suspend and resume count for the
current thread and resumes tracing the thread if the result is not negative.
282 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 31. Using the Reliability, Availability, and
Serviceability Interface
The JVM Reliability, Availability, and Serviceability Interface (JVMRI) allows an
agent to access reliability, availability, and serviceability (RAS) functions by using a
structure of pointers to functions. You can use the interface to:
v Determine the trace capability that is present
v Set and intercept trace data
v Produce various dumps
v Inject errors
You need some programming skills to use the JVMRI. You must be able to build a
native library, add the code for JVMRI callbacks (described below), and interface
the code to the JVM through the JNI. This book provides the callback code but
does not provide the other programming information.
Writing an agent
The following piece of code demonstrates how to write a very simple JVMRI
agent. When an agent is loaded by the JVM, the first thing that gets called is the
entry point routine JVM_OnLoad(). Therefore, your agent must have a routine
called JVM_OnLoad(). This routine then must obtain a pointer to the JVMRI
function table. This is done by making a call to the GetEnv() function.
/* jvmri - jvmri agent source file. */
#include "jni.h"
#include "jvmri.h"
/*
* Get a pointer to the JNIEnv
*/
/*
* Get a pointer to the JVMRI function table
*/
/*
* Now a pointer to the function table has been obtained we can make calls to any
* of the functions in that table.
*/
.........................................................
return rc;
}
An agent can register a function that is called back when the JVM makes a trace
point. The following example shows a trace listener that only increments a counter
each time a trace point is taken.
void JNICALL
listener(void *env, void ** tl, unsigned int traceId, const char * format,
va_list var)
{
int *counter;
if (*tl == NULL) {
fprintf(stderr, "RASplugin100 first tracepoint for thread %p\n", env);
*tl = (void *)malloc(4);
counter = (int *)*tl;
*counter = 0;
}
(*counter)++;
284 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Registering a trace listener
rc = jvmri_intf->TraceRegister(env, listener);
if (rc != JNI_OK) {
fprintf(stderr, "RASplugin003 Return code %d registering listener\n", rc);
fflush(stderr);
return JNI_ERR;
}
You can also do more difficult operation with a trace listener, including formatting
the trace point information yourself then displaying this or perhaps recording it in
a file or database
To set Maximal tracing for ’j9mm’, use the following command when launching the
JVM and your agent:
java -Xrunjvmri:maximal=j9mm -Xtrace:external=j9mm App.class
Note: Trace must be enabled before the agent can be used. To do this, specify the
trace option on the command-line: -Xtrace:external=j9mm.
Chapter 31. Using the Reliability, Availability, and Serviceability Interface 285
Launching the agent
Linux
To build a JVMRI agent, write a shell script similar to this:
export SDK_BASE=<sdk directory>
export INCLUDE_DIRS="-I. -I$SDK_BASE/include"
export JVM_LIB=-L$SDK_BASE/jre/bin/classic
gcc $INCLUDE_DIRS $JVM_LIB -ljvm -o libmyagent.so -shared myagent.c
z/OS
To build a JVMRI agent, write a shell script similar to this:
SDK_BASE= <sdk directory>
USER_DIR= <user agent’s source directory>
c++ -c -g -I$SDK_BASE/include -I$USER_DIR -W "c,float(ieee)"
-W "c,langlvl(extended)" -W "c,expo,dll" myagent.c
c++ -W "l,dll" -o libmyagent.so myagent.o
chmod 755 libmyagent.so
Agent design
The agent must reference the header files jni.h and jvmri.h, which are shipped with
the SDK and are in the sdk\include subdirectory. To launch the agent, use the
-Xrun command-line option. The JVM parses the -Xrunlibrary_name[:options]
switch and loads library_name if it exists. A check for an entry point that is called
JVM_OnLoad is then made. If the entry point exists, it is called to allow the library to
initialize. This processing occurs after the initialization of all JVM subcomponents.
The agent can then call the functions that have been initialized, by using the
JVMRI table.
JVMRI functions
At startup, the JVM initializes JVMRI. You access the JVMRI functions with the JNI
GetEnv() routine to obtain an interface pointer. For example:
JNIEXPORT jint JNICALL
JVM_OnLoad(JavaVM *vm, char *options, void *reserved)
{
DgRasInterface *ri;
......
(*vm)->GetEnv(vm, (void **)&ri, JVMRAS_VERSION_1_3)
rc = jvmras_intf->TraceRegister(env, listener);
......
}
CreateThread
int CreateThread( JNIEnv *env, void JNICALL (*startFunc)(void*),
void *args, int GCSuspend)
Description
Creates a thread. A thread can be created only after the JVM has been
initialized. However, calls to CreateThread can be made also before
initialization; the threads are created by a callback function after initialization.
286 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JVMRI - API calls
Parameters
v A valid pointer to a JNIEnv.
v Pointer to start function for the new thread.
v Pointer to argument that is to be passed to start function.
v GCSuspend parameter is ignored.
Returns
JNI Return code JNI_OK if thread creation is successful; otherwise, JNI_ERR.
DumpDeregister
int DumpDeregister(JNIEnv *env, int (JNICALL *func)(JNIEnv *env2,
void **threadLocal, int reason))
Description
Deregisters a dump call back function that was previously registered by a call
to DumpRegister.
Parameters
v A valid pointer to a JNIEnv.
v Function pointer to trace function to register.
Returns
JNI return codes JNI_OK and JNI_EINVAL.
DumpRegister
int DumpRegister(JNIEnv *env, int (JNICALL *func)(JNIEnv *env2,
void **threadLocal, int reason))
Description
Registers a function that is called back when the JVM is about to generate a
JavaCore file.
Parameters
v A valid pointer to a JNIEnv.
v Function pointer to trace function to register.
Returns
JNI return codes JNI_OK and JNI_ENOMEM.
DynamicVerbosegc
void JNICALL *DynamicVerbosegc (JNIEnv *env, int vgc_switch,
int vgccon, char* file_path, int number_of_files,
int number_of_cycles);
Description
Not supported. Displays the message ″not supported″.
Parameters
v A valid pointer to a JNIEnv.
v Integer that indicates the direction of switch (JNI_TRUE = on, JNI_FALSE =
off)
v Integer that indicates the level of verbosegc (0 = -verbosegc, 1 =
-verbose:Xgccon)
v Pointer to string that indicates file name for file redirection
v Integer that indicates the number of files for redirection
v Integer that indicates the number of cycles of verbosegc per file
Chapter 31. Using the Reliability, Availability, and Serviceability Interface 287
JVMRI - API calls
Returns
None.
GenerateHeapdump
int GenerateHeapdump( JNIEnv *env )
Description
Generates a Heapdump file.
Parameters
v A valid pointer to a JNIEnv.
Returns
JNI Return code JNI_OK if running dump is successful; otherwise, JNI_ERR.
GenerateJavacore
int GenerateJavacore( JNIEnv *env )
Description
Generates a Javacore file.
Parameters
v A valid pointer to a JNIEnv.
Returns
JNI Return code JNI_OK if running dump is successful; otherwise, JNI_ERR.
GetComponentDataArea
int GetComponentDataArea( JNIEnv *env, char *componentName,
void **dataArea, int *dataSize )
Description
Not supported. Displays the message ″no data area for <requested
component>″
Parameters
v A valid pointer to a JNIEnv.
v Component name.
v Pointer to the component data area.
v Size of the data area.
Returns
JNI_ERR
GetRasInfo
int GetRasInfo(JNIEnv * env,
RasInfo * info_ptr)
Description
This function fills in the supplied RasInfo structure, based on the request type
that is initialized in the RasInfo structure. (See details of the RasInfo structure
in “RasInfo structure” on page 292.
Parameters
v A valid pointer to a JNIEnv. This parameter is reserved for future use.
v Pointer to a RasInfo structure. This should have the type field initialized to a
supported request.
288 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JVMRI - API calls
Returns
JNI Return codes JNI_OK, JNI_EINVAL and JNI_ENOMEM.
InitiateSystemDump
int JNICALL InitiateSystemDump( JNIEnv *env )
Description
Initiates a system dump. The dumps and the output that are produced depend
on the settings for JAVA_DUMP_OPTS and JAVA_DUMP_TOOL and on the
support that is offered by each platform.
Parameters
v A valid pointer to a JNIEnv.
Returns
JNI Return code JNI_OK if dump initiation is successful; otherwise, JNI_ERR. If a
specific platform does not support a system-initiated dump, JNI_EINVAL is
returned.
InjectOutOfMemory
int InjectOutOfMemory( JNIEnv *env )
Description
Not supported. Displays the message ″not supported″.
Parameters
v A valid pointer to a JNIEnv.
Returns
JNI_ERR
InjectSigSegv
int InjectSigsegv( JNIEnv *env )
Description
Raises a SIGSEGV exception, or the equivalent for your platform.
Parameters
v A valid pointer to a JNIEnv.
Returns
JNI_ERR
NotifySignal
void NotifySignal(JNIEnv *env, int signal)
Description
Raises a signal in the JVM.
Parameters
v A valid pointer to a JNIEnv. This parameter is reserved for future use.
v Signal number to raise.
Returns
Nothing.
Chapter 31. Using the Reliability, Availability, and Serviceability Interface 289
JVMRI - API calls
ReleaseRasInfo
int ReleaseRasInfo(JNIEnv * env,
RasInfo * info_ptr)
Description
This function frees any areas to which the RasInfo structure might point after a
successful GetRasInfo call. The request interface never returns pointers to ’live’
JVM control blocks or variables.
Parameters
v A valid pointer to a JNIEnv. This parameter is reserved for future use.
v Pointer to a RasInfo structure. This should have previously been set up by a
call to GetRasInfo. An error occurs if the type field has not been initialized
to a supported request. (See details of the RasInfo structure in “RasInfo
structure” on page 292.)
Returns
JNI Return codes JNI_OK or JNI_EINVAL.
RunDumpRoutine
int RunDumpRoutine( JNIEnv *env, int componentID, int level, void (*printrtn)
(void *env, const char *tagName, const char *fmt, ...) )
Description
Runs one of the individual registered dump routines. Output is sent to the
supplied print routine.
Parameters
v A valid pointer to a JNIEnv.
v Id of component to dump.
v Detail level of dump.
v Print routine to which dump output is directed.
Returns
JNI Return code JNI_OK if running dump is successful; otherwise, JNI_ERR.
SetOutOfMemoryHook
int SetOutOfMemoryHook( JNIEnv *env, void (*rasOutOfMemoryHook)
(void) )
Description
Registers a callback function for an out-of-memory condition.
Parameters
v A valid pointer to a JNIEnv.
v Pointer to callback function.
Returns
JNI Return code JNI_OK if table is successfully updated; otherwise, JNI_ERR.
TraceDeregister
int TraceDeregister(JNIEnv *env, void (JNICALL *func)(JNIEnv *env2,
void **threadLocal, int traceId, const char *
format, va_list varargs))
Description
Deregisters an external trace listener.
290 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JVMRI - API calls
Parameters
v A valid pointer to a JNIEnv.
v Function pointer to a previously-registered trace function.
Returns
JNI Return code JNI_OK or JNI_EINVAL.
TraceRegister
int TraceRegister(JNIEnv *env, void (JNICALL *func)(JNIEnv *env2,
void **threadLocal, int traceId, const char * format,
va_list var))
Description
Registers a trace listener.
Parameters
v A valid pointer to a JNIEnv.
v Function pointer to trace function to register.
Returns
JNI Return code JNI_OK or JNI_ENOMEM.
TraceResume
void TraceResume(JNIEnv *env)
Description
Resumes tracing.
Parameters
v A valid pointer to a JNIEnv. If MULTI_JVM; otherwise, it can be NULL.
Returns
Nothing.
TraceResumeThis
void TraceResumeThis(JNIEnv *env);
Description
Resume tracing from the current thread. This action decrements the
resumecount for this thread. When it reaches zero (or below) the thread starts
tracing (see Chapter 30, “Tracing Java applications and the JVM,” on page 259).
Parameters
v A valid pointer to a JNIEnv.
Returns
None.
TraceSet
int TraceSet(JNIEnv *env, const char *cmd)
Description
Sets the trace configuration options.
Parameters
v A valid pointer to a JNIEnv.
v Trace configuration command.
Chapter 31. Using the Reliability, Availability, and Serviceability Interface 291
JVMRI - API calls
Returns
JNI Return code JNI_OK, JNI_ERR, JNI_ENOMEM, JNI_EXIST and JNI_EINVAL.
TraceSnap
void TraceSnap(JNIEnv *env, char *buffer)
Description
Takes a snapshot of the current trace buffers.
Parameters
v A valid pointer to a JNIEnv; if set to NULL, current Execenv is used.
v The second parameter is no longer used, but still exists to prevent changing
the function interface. It can safely be set to NULL.
Returns
Nothing
TraceSuspend
void TraceSuspend(JNIEnv *env)
Description
Suspends tracing.
Parameters
v A valid pointer to a JNIEnv; if MULTI_JVM; otherwise, it can be NULL.
Returns
Nothing.
TraceSuspendThis
void TraceSuspendThis(JNIEnv *env);
Description
Suspend tracing from the current thread. This action decrements the
suspendcount for this thread. When it reaches zero (or below) the thread stops
tracing (see Chapter 30, “Tracing Java applications and the JVM,” on page 259).
Parameters
v A valid pointer to a JNIEnv.
Returns
None.
RasInfo structure
The RasInfo structure that is used by GetRasInfo() takes the following form.
(Fields that are initialized by GetRasInfo are underscored):
typedef struct RasInfo {
int type;
union {
struct {
int number;
char **names;
} query;
struct {
int number;
char **names;
} trace_components;
struct {
char *name
292 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
RasInfo, trace, and formatting
int first;
int last;
unsigned char *bitMap;
} trace_component;
} info;
} RasInfo;
The -Xtrace:external=<option>
The format of this property is:
-Xtrace:external=[[!]tracepoint_specification[,...]]
This system property controls what is traced. Multiple statements are allowed and
their effect is cumulative.
If no qualifier parameters are entered, all tracepoints are enabled; that is, the
equivalent of specifying all.
Chapter 31. Using the Reliability, Availability, and Serviceability Interface 293
RasInfo, trace, and formatting
Formatting
You can use J9TraceFormat.dat to format JVM-generated tracepoints that are
captured by the agent. J9TraceFormat.dat is shipped with the SDK. It consists of a
flat ASCII or EBCDIC file of the following format:
1.2
dg
000100 8 00 0 N DgTrcRecordsLost "***** %d records lost *****"
000101 0 00 0 N dgTraceLock_Event1 "dgTraceLock() Trace suspended and locked "
000102 0 00 0 N dgTraceUnlock_Event1 "dgTraceUnlock() Trace resumed and unlocked"
The first line contains the version number of the format file. A new version
number reflects changes to the layout of this file. The second line contains the
internal JVM component name. Following the component name are the tracepoint
formatting records for the named component. These formatting records continue
until another component name is found. (Component name entries can be
distinguished from format records, because they always contain only one field.)
where:
v nnnnnn is the hex tracepoint ID.
v t is the tracepoint type (0 through 11).
v o is the overhead (0 through 10).
v l is the level of the tracepoint (0 through 9, or - if the tracepoint is obsolete).
v e is the explicit setting flag (Y/N).
v symbolic_name is the name of the tracepoint.
294 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
RasInfo, trace, and formatting
Any other type is reserved for development use; you should not find any on a
retail build. Note that this condition is subject to change without notice. The
version number will be different for each change.
Chapter 31. Using the Reliability, Availability, and Serviceability Interface 295
RasInfo, trace, and formatting
296 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 32. Using the JVMPI
The JVMPI is a 2-way interface that allows communication between the JVM and a
profiler. JVMPI allows third parties to develop profiling tools based on this
interface. The interface contains mechanisms for the profiling agent to notify the
JVM about the kinds of information it wants to receive as well as a means of
receiving the relevant notifications. Several tools are based on this interface, such
as Jprobe, OptimizeIt, TrueTime, and Quantify. These are all third-party commercial
tools, so IBM cannot make any guarantees or recommendations with regard to
their use. IBM does provide a simple profiling agent, based on this interface, called
HPROF.
When you run Java with HPROF, an output file is created at the end of program
execution. This file is placed in the current working directory and is called
java.hprof.txt (java.hprof if binary format is used) unless a different filename has
been given. This file contains a number of different sections, but the exact format
and content depend on the selected options.
time different threads are spending when trying to access resources that are
already locked. HPROF also gives you a snapshot of the monitors in use. This
is very useful for detecting deadlocks.
format=a|b
The default is for the output file to be in ASCII format. Set format to ’b’ if you
want to specify a binary format (which is required for some utilities such as
the Heap Analysis Tool).
file=<filename>
The file option lets you change the name of the output file. The default name
for an ASCII file is java.hprof.txt. The default name for a binary file is
java.hprof.
net=<host>:<port>
To send the output over the network rather than to a local file, use the net
option.
depth=<size>
The depth option indicates the number of method frames to display in a stack
trace (the default is 4).
thread=y|n
If you set the thread option to ″y″, the thread id is printed beside each trace.
This option is useful if it is not clear which thread is associated with which
trace (a problem that might occur in a multi-threaded application).
doe=y|n
The default behavior is to collect profile information when an application exits.
To collect the profiling data during execution, set doe (dump on exit) to ″n″.
You can see the output after using HPROF with a simple program, as shown
below. This test program creates and runs two threads for a short time. From the
output, you can see that the two threads called respectively ″apples″ and ″oranges″
were created after the system-generated ″main″ thread. Both threads end before the
″main″ thread. For each thread its address, identifier, name, and thread group
name are displayed. You can see the order in which threads start and finish.
THREAD START (obj=11199050, id = 1, name="Signal dispatcher", group="system")
THREAD START (obj=111a2120, id = 2, name="Reference Handler", group="system")
THREAD START (obj=111ad910, id = 3, name="Finalizer", group="system")
THREAD START (obj=8b87a0, id = 4, name="main", group="main")
THREAD END (id = 4)
THREAD START (obj=11262d18, id = 5, name="Thread-0", group="main")
THREAD START (obj=112e9250, id = 6, name="apples", group="main")
THREAD START (obj=112e9998, id = 7, name="oranges", group="main")
THREAD END (id = 6)
THREAD END (id = 7)
THREAD END (id = 5)
The trace output section contains regular stack trace information. The depth of
each trace can be set and each trace has a unique id:
TRACE 5:
java/util/Locale.toLowerCase(Locale.java:1188)
java/util/Locale.convertOldISOCodes(Locale.java:1226)
java/util/Locale.<init>(Locale.java:273)
java/util/Locale.<clinit>(Locale.java:200)
298 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JVMPI - HPROF profiler
A trace contains a number of frames, and each frame contains the class name,
method name, filename, and line number. In the example above you can see that
line number 1188 of Local.java (which is in the toLowerCase method) has been
called from the convertOldISOCodes() function in the same class. These traces are
useful in following the execution path of your program. If you set the monitor
option, a monitor dump is output that looks like this:
MONITOR DUMP BEGIN
THREAD 8, trace 1, status: R
THREAD 4, trace 5, status: CW
THREAD 2, trace 6, status: CW
THREAD 1, trace 1, status: R
MONITOR java/lang/ref/Reference$Lock(811bd50) unowned
waiting to be notified: thread 2
MONITOR java/lang/ref/ReferenceQueue$Lock(8134710) unowned
waiting to be notified: thread 4
RAW MONITOR "_hprof_dump_lock"(0x806d7d0)
owner: thread 8, entry count: 1
RAW MONITOR "Monitor Cache lock"(0x8058c50)
owner: thread 8, entry count: 1
RAW MONITOR "Monitor Registry lock"(0x8058d10)
owner: thread 8, entry count: 1
RAW MONITOR "Thread queue lock"(0x8058bc8)
owner: thread 8, entry count: 1
MONITOR DUMP END
MONITOR TIME BEGIN (total = 0 ms) Thu Aug 29 16:41:59 2002
MONITOR TIME END
The first part of the monitor dump contains a list of threads, including the trace
entry that identifies the code the thread executed. There is also a thread status for
each thread where:
v R — Runnable
v S — Suspended
v CW — Condition Wait
v MW — Monitor Wait
Next is a list of monitors along with their owners and an indication of whether
there are any threads waiting on them.
The Heapdump is the next section. This is a list of different areas of memory and
shows how they are allocated:
CLS 1123edb0 (name=java/lang/StringBuffer, trace=1318)
super 111504e8
constant[25] 8abd48
constant[32] 1123edb0
constant[33] 111504e8
constant[34] 8aad38
constant[115] 1118cdc8
CLS 111ecff8 (name=java/util/Locale, trace=1130)
super 111504e8
constant[2] 1117a5b0
constant[17] 1124d600
constant[24] 111fc338
constant[26] 8abd48
constant[30] 111fc2d0
constant[34] 111fc3a0
constant[59] 111ecff8
constant[74] 111504e8
constant[102] 1124d668
...
CLS 111504e8 (name=java/lang/Object, trace=1)
constant[18] 111504e8
CLS tells you that memory is being allocated for a class. The hexadecimal number
following it is the actual address where that memory is allocated.
Next is the class name followed by a trace reference. Use this to cross reference the
trace output and see when this is called. If you refer back to that particular trace,
you can get the actual line number of code that led to the creation of this object.
The addresses of the constants in this class are also displayed and, in the above
example, the address of the class definition for the superclass. Both classes are
children of the same superclass (with address 11504e8). Looking further through
the output you can see this class definition and name. It turns out to be the Object
class (a class that every class inherits from). The JVM loads the entire superclass
hierarchy before it can use a subclass. Thus, class definitions for all superclasses
are always present. There are also entries for Objects (OBJ) and Arrays (ARR):
OBJ 111a9e78 (sz=60, trace=1, class=java/lang/Thread@8b0c38)
name 111afbf8
group 111af978
contextClassLoader 1128fa50
inheritedAccessControlContext 111aa2f0
threadLocals 111bea08
inheritableThreadLocals 111bea08
ARR 8bb978 (sz=4, trace=2, nelems=0, elem type=java/io/ObjectStreamField@8bac80)
If you set the heap option to ″sites″ or ″all″ (″dump″ and ″sites″), you also get a list
of each area of storage allocated by your code. This list is ordered with the sites
that allocate the most memory at the top:
SITES BEGIN (ordered by live bytes) Thu Aug 29 16:30:31 2002
percent live alloc’ed stack class
rank self accum bytes objs bytes objs trace name
1 18.18% 18.18% 32776 2 32776 2 1332 [C
2 9.09% 27.27% 16392 2 16392 2 1330 [B
3 8.80% 36.08% 15864 92 15912 94 1 [C
4 4.48% 40.55% 8068 1 8068 1 31 [S
5 4.04% 44.59% 7288 4 7288 4 1130 [C
6 3.12% 47.71% 5616 36 5616 36 1 <Unknown>
7 2.51% 50.22% 4524 29 4524 29 1 java/lang/Class
8 2.05% 52.27% 3692 1 3692 1 806 [L<Unknown>;
9 2.01% 54.28% 3624 90 3832 94 77 [C
10 1.40% 55.68% 2532 1 2532 1 32 [I
11 1.37% 57.05% 2468 3 2468 3 1323 [C
12 1.31% 58.36% 2356 1 2356 1 1324 [C
13 1.14% 59.50% 2052 1 2052 1 95 [B
14 1.02% 60.52% 1840 92 1880 94 1 java/lang/String
15 1.00% 61.52% 1800 90 1880 94 77 java/lang/String
16 0.64% 62.15% 1152 10 1152 10 1390 [C
17 0.57% 62.72% 1028 1 1028 1 30 [B
18 0.52% 63.24% 936 6 936 6 4 <Unknown>
19 0.45% 63.70% 820 41 820 41 79 java/util/Hashtable$Entry
In this example, Trace 1332 allocated 18.18% of the total allocated memory. This
works out to be 32776 bytes.
The cpu option gives profiling information on the CPU. If cpu is set to samples,
you get an output containing the results of periodic samples during execution of
the code. At each sample, the code path being executed is recorded and a report
such as this is output:
CPU SAMPLES BEGIN (total = 714) Fri Aug 30 15:37:16 2002
rank self accum count trace method
1 76.28% 76.28% 501 77 MyThread2.bigMethod
2 6.92% 83.20% 47 75 MyThread2.smallMethod
...
CPU SAMPLES END
300 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JVMPI - HPROF profiler
You can see that the bigMethod() was responsible for 76.28% of the CPU execution
time and was being executed 501 times out of the 714 samples. If you use the trace
IDs, you can see the exact route that led to this method being called.
302 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Chapter 33. Using DTFJ
The Diagnostic Tooling Framework for Java (DTFJ) is a Java application
programming interface (API) from IBM used to support the building of Java
diagnostics tools.
You process the dumps passed to DTFJ with the jextract tool; see “jextract” on
page 223. The jextract tool produces metadata from the dump, which allows the
internal structure of the JVM to be analyzed. jextract must be run on the system
that produced the dump.
The DTFJ API helps diagnostics tools access the following (and more) information:
v Memory locations stored in the dump
v Relationships between memory locations and Java internals
v Java threads running within the JVM
v Native threads held in the dump
v Java classes and objects that were present in the heap
v Details of the machine on which the dump was produced
v Details of the Java version that was being used
v The command line that launched the JVM
DTFJ is implemented in pure Java and tools written using DTFJ can be
cross-platform. Therefore, it is possible to analyze a dump taken from one machine
on another (remote and more convenient) machine. For example, a dump produced
on an AIX PPC machine can be analyzed on a Windows Thinkpad.
The full details of the DTFJ Interface are provided with the SDK as Javadoc in
sdk/docs/dtfj.zip. DTFJ classes are accessible without modification to the class
path.
Figure 10 on page 306 illustrates the DTFJ interface. The starting point for working
with a dump is to obtain an Image instance by using the ImageFactory class
supplied with the concrete implementation of the API.
import com.ibm.dtfj.image.CorruptData;
import com.ibm.dtfj.image.Image;
import com.ibm.dtfj.image.ImageFactory;
In this example, the only section of code that ties the dump to a particular
implementation of DTFJ is the generation of the factory class – it would be a
straightforward task to amend this code to cope with handling different
implementations.
The getImage() methods in ImageFactory expect two files. The files must be the
dump itself and the .xml metadata file. If there is a problem with the file specified,
an IOException is thrown by getImage() and can be caught and (in the example
above) an appropriate message issued. If a missing file was passed to the above
example, the following output would be produced:
304 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Overview of the DTFJ interface
at java.io.FileInputStream.<init>(FileInputStream.java:135)
at com.ibm.dtfj.image.j9.ImageFactory.getImage(ImageFactory.java:47)
at com.ibm.dtfj.image.j9.ImageFactory.getImage(ImageFactory.java:35)
at DTFJEX1.main(DTFJEX1.java:23)
In the case above, the DTFJ implementation is expecting a dump file to exist.
Different errors would be caught if the file existed but was not recognized as a
valid dump file.
After you have obtained an Image instance, you can begin analyzing the dump.
The Image instance is the second instance in the class hierarchy for DTFJ
illustrated by Figure 10 on page 306.
KEY
ImageFactory
P P
ImageStackFrame ImageRegister ImageSymbol
java Package
P
JavaRuntime
P
JavaThread JavaClassLoader JavaMonitor
JavaHeap
S
P P
JavaStackFrame JavaMethod JavaClass
S
P
JavaLocation JavaField
P
JavaMember JavaObject
S
The hierarchy displays some major points of DTFJ. Firstly, there is a separation
between the Image (the dump, a sequence of bytes with different contents on
different platforms) and the Java internal knowledge.
306 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Overview of the DTFJ interface
v The DTFJ interface is separated into two parts: classes with names that start with
Image and classes with names that start with Java.
v Image and Java classes are linked using a ManagedRuntime (which is extended
by JavaRuntime).
v An Image object contains one ImageAddressSpace object (or, on z/OS, possibly
more).
v An ImageAddressSpace object contains one ImageProcess object (or, on z/OS,
possibly more).
v Conceptually, you can apply the Image model to any program running with the
ImageProcess, although for the purposes of this document discussion is limited
to the IBM JVM implementations.
In this example, the program iterates through every available Java thread and
checks whether it is equal to any of the available image threads. When they are
found to be equal, the program declares that it has, in this case, "Found a match".
import com.ibm.dtfj.image.CorruptData;
import com.ibm.dtfj.image.CorruptDataException;
import com.ibm.dtfj.image.Image;
import com.ibm.dtfj.image.ImageAddressSpace;
import com.ibm.dtfj.image.ImageFactory;
import com.ibm.dtfj.image.ImageProcess;
import com.ibm.dtfj.java.JavaRuntime;
import com.ibm.dtfj.java.JavaThread;
import com.ibm.dtfj.image.ImageThread;
} else {
System.err.println("No filename specified");
}
if (null == image) {
return;
}
MatchingThreads(image);
}
while (prIt.hasNext()) {
System.out.println("Found ImageProcess...");
while (javaThreadIt.hasNext()) {
Object tempObj = javaThreadIt.next();
/* Should use CorruptData
* handling for all iterators
*/
if (tempObj instanceof CorruptData) {
System.out.println("We have some corrupt data");
} else {
JavaThread javaThread = (JavaThread) tempObj;
System.out.println("Found JavaThread...");
try {
imgThread = (ImageThread) javaThread
.getImageThread();
while (imgThreadIt.hasNext()) {
ImageThread imgThread2 = (ImageThread) imgThreadIt
.next();
if (imgThread.equals(imgThread2)) {
System.out.println("Found a match:");
System.out.println("\tjavaThread "
+ javaThread.getName()
+ " is the same as "
+ imgThread2.getID());
}
}
} catch (CorruptDataException e) {
System.err.println("ImageThread was corrupt: " + e.getMessage());
}
308 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
DTFJ example application
}
}
}
}
}
}
ftp://ftp.software.ibm.com/software/webserver/appserv/library/wasv5base_pd.pdf
or
http://www-3.ibm.com/software/webservers/appserv/was/library/
or the WAS problem determination guide:
http://www.redbooks.ibm.com/abstracts/sg246798.html
entries that are to be kept in the buffer at any given time. Specify the size of
the buffer in thousands of entries. For example, if you want 1000 entries,
specify 1; if you want 3000 entries, specify 3.
12. Select the desired format for the generated trace.
13. Save the changed configuration.
14. Start the server.
316 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Appendix C. CORBA GIOP message format
Table 18 shows:
v All types of messages
v The values of those messages as an integer number
v Whether those messages contain only a header or a header and a body
v Whether those messages are supported in GIOP versions 1.0, 1.1, and 1.2
Table 18. CORBA GIOP messages
Message Value Header Body 1.0 or 1.1 1.2 supported
supported
Request 0 X X X X
Reply 1 X X X X
Cancel 2 X X X
Request
Locate 3 X X X
request
Locate reply 4 X X X X
Close 5 X X
connection
Message error 6 X X
Fragment 7 X X X
Note: From now on in this chapter, each cell (table column) represents 1 byte
unless specified otherwise. Alignment of fields is not specified in the
following byte description. In a GIOP message, some fields must start at a 4-
or 8-byte boundary. Extra bytes of padding are present (always set to 0).
GIOP header
All types of messages that are described in Appendix C, “CORBA GIOP message
format” start with the GIOP Message Header:
47=G 49=I 4F=0 50=P Major; for Minor; for Flags Value (4 bytes)
example, example, length of
01 02 the rest of
the
message
In GIOP1.0, the least-significant bit of the Flags byte (that is, the first bit on the
right of the byte) indicates the byte sequence (big endian or little endian). In GIOP
1.1 and 1.2, the least-significant bit indicates the byte sequence that is used in later
elements of the message. A value of false (0) indicates a big-endian byte
sequencing; true (1) indicates little-endian byte sequencing.
The bit that is immediately to the left of the least-significant bit indicates whether
or not more fragments follow. A value of false (0) indicates that this message is the
last fragment; true (1) indicates that more fragments follow this message. The
most-significant six bits are reserved; for GIOP 1.2 (1.1) they must be set to zero.
The Value field is the field that is indicated in Appendix C, “CORBA GIOP
message format,” on page 317.
Request header
Request id (4 bytes) Response Expected Reserved Reserved Reserved
The Response Expected flag indicates whether this request expects a reply from the
server. Values 1 = WITH_SERVER and 3 = WITH_TARGET correspond to a true
value. Therefore, the client expects a reply. A value of 0 = NONE or
WITH_TRANSPORT means that no reply is required. The reserved bytes are for
future use.
After this first 8 bytes, the header continues with the specification of the remote
reference. This specification, however, differs in different version of the GIOP. In
GIOP 1.0 and 1.1, the specification is:
Length of the Object Key (4 bytes) Object key (see previous length in bytes)
In GIOP 1.2, the specification is more complex. The next value of Addressing
Disposition index decides whether to insert an object key, a profile, or a full IOR
(one row corresponds to one value):
and a sequence of N service contexts must come next. The following describes how
one of these service contexts is written. N of them are written consecutively.
Service context ID (4 bytes) Service context length (4 bytes) Service context data
Request body
Marshaled parameters (CORBA valuetype) Context pseudo object (for GIOP 1.0/1.1 only)
Reply header
For GIOP 1.2:
318 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
CORBA GIOP message format
Number of service contexts (4 bytes) < sequence of service contexts as before >
Note: In GIOP 1.0/1.1, the request ID and the reply status comes after the service
context list.
Marshaled parameters
v LOCATE_FORWARD:
GIOP 1.0/1.1 supports only the object key version (first row only) and no
addressing disposition is specified.
Fragment message
The fragment message observes these rules:
v The fragment length plus the GIOP header length (12 bytes) is a multiple of 8
for all but last message.
v All fragments must include at least the GIOP header and the request ID (total
length 16 bytes).
v In the GIOP header of the first fragment, the message type can be request,
reply, locate request, and locate reply. The fragment flag is set to 1.
v In the fragments that follow the first one, the message type is Fragment, and
the fragment flag is set to 1, except in the last fragment where the flag is set to
0.
320 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Appendix D. CORBA minor codes
This appendix gives definitions of the most common OMG- and IBM-defined
CORBA system exception minor codes that the IBM Java ORB uses. (See
“Completion status and minor codes” on page 169 for more information about
minor codes.)
When an error occurs, you might find additional details in the ORB FFDC log. By
default, the IBM Java ORB creates an FFDC log whose name is of the form
orbtrc.DDMMYYY.HHmm.SS.txt. If the IBM Java ORB is operating in the WebSphere
Application Server or other IBM product, see the publications for that product to
determine the location of the FFDC log.
org.omg.CORBA.COMM_FAILURE
CONNECT_FAILURE_1
User response: Investigate each request and reissue if
Explanation: The client attempted to open a
necessary. If the problem reoccurs, run with ORB,
connection with the server, but failed. The reasons for
network tracing, or both, active to determine the cause
the failure can be many; for example, the server might
of the failure.
not be up or it might not be listening on that port. If a
BindException is caught, it shows that the client could
not open a socket locally (that is, the local port was in CREATE_LISTENER_FAILED
use or the client has no local address).
Explanation: An exception occurred while a TCP/IP
Applicable CORBA exception class: listener was being created.
org.omg.CORBA.TRANSIENT
Applicable CORBA exception class:
User response: As with all TRANSIENT exceptions, a org.omg.CORBA.INTERNAL
retry or restart of the client or server might solve the
problem. Ensure that the port and server host names User response: The details of the caught exception are
are correct, and that the server is running and allowing written to the FFDC log. Review the details of the
connections. Also ensure that no firewall is blocking the exception, and take any further action that is necessary.
connection, and that a route is available between client
and server. LOCATE_UNKNOWN_OBJECT
Explanation: The server has no knowledge of the
CONN_CLOSE_REBIND object for which the client has asked in a locate request.
Explanation: An attempt has been made to write to a Applicable CORBA exception class:
TCP/IP connection that is closing. org.omg.CORBA.OBJECT_NOT_EXIST
Applicable CORBA exception class: User response: Ensure that the remote object that is
org.omg.CORBA.COMM_FAILURE requested resides in the specified server and that the
User response: Ensure that the completion status that remote reference is up-to-date.
is associated with the minor code is NO, then reissue
the request. NULL_PI_NAME
Explanation: One of the following methods has been
CONN_PURGE_ABORT called:
Explanation: An unrecoverable error occurred on a org.omg.PortableInterceptor.ORBInitInfoOperations.
TCP/IP connection. All outstanding requests are add_ior_interceptor
canceled. Errors include:
org.omg.PortableInterceptor.ORBInitInfoOperations.
v A GIOP MessageError or unknown message type add_client_request_interceptor
v An IOException that is received while data was
being read from the socket org.omg.PortableInterceptor.ORBInitInfoOperations
.add_server_request_interceptor
v An unexpected error or exception that occurs during
message processing
The name() method of the interceptor input parameter
Applicable CORBA exception class: returned a null string.
POA_DISCARDING UNSPECIFIED_MARSHAL_25
Explanation: The POA Manager at the server is in the Explanation: This error can occur at the server side
discarding state. When a POA manager is in the while the server is reading a request, or at the client
discarding state, the associated POAs discard all side while the client is reading a reply. Possible causes
incoming requests (whose processing has not yet are that the data on the wire is corrupted, or the server
begun). For more details, see the section that describes and client ORB are not communicating correctly.
the POAManager Interface in the http:// Communication problems can caused when one of the
www.omg.org/cgi-bin/doc?formal/99-10-07. ORBs has an incompatibility or bug that prevents it
Applicable CORBA exception class: from conforming to specifications.
org.omg.CORBA.TRANSIENT Applicable CORBA exception class:
User response: Put the POA Manager into the active org.omg.CORBA.MARSHAL
state if you want requests to be processed. User response: Check whether the IIOP levels and
CORBA versions of the client and server are
RESPONSE_INTERRUPTED compatible. Try disabling fragmentation (set
com.ibm.CORBA.FragmentationSize to zero) to
Explanation: The client has enabled the determine whether it is a fragmentation problem. In
AllowUserInterrupt property and has called for an this case, analysis of CommTraces
interrupt on a thread currently waiting for a reply from (com.ibm.CORBA.CommTrace) might give extra
a remote method call. information.
Applicable CORBA exception class:
org.omg.CORBA.NO_RESPONSE
User response: None.
TRANS_NC_LIST_GOT_EXC
Explanation: An exception was caught in the
NameService while the NamingContext.List() method
was executing.
Applicable CORBA exception class:
org.omg.CORBA.INTERNAL
User response: The details of the caught exception are
written to the FFDC log. Review the details of the
original exception, and any further action that is
necessary.
322 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Appendix E. Environment variables
This appendix provides the following information about environment variables:
v “Displaying the current environment”
v “Setting an environment variable”
v “Separating values in a list”
v “JVM environment settings”
v “z/OS environment variables” on page 326
These variables are set only for the current shell or command-line session.
324 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Environment variables
326 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Environment variables
328 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Appendix F. Command-line options
You can specify the options on the command-line while you are starting Java. They
override any relevant environment variables. For example, using -cp <dir1> with
the Java command completely overrides setting the environment variable
CLASSPATH=<dir2>.
-showversion
Prints product version and continues.
-memorycheck[:quick | nofree]
Identifies memory leaks inside the JVM.
v quick – less extensive checks
v nofree – does not free reused memory
-verbose[:class | gc | jni]
Enables verbose output.
-verbose:dynload
Provides detailed information as each class is loaded by the JVM, including:
v The class name and package
v For class files that were in a .jar file, the name and directory path of the .jar
v Details of the size of the class and the time taken to load the class
The data is written out to stderr. An example of the output follows:
<Loaded java/lang/String from C:\sdk\jre\lib\vm.jar>
<Class size 17258; ROM size 21080; debug size 0>
<Read time 27368 usec; Load time 782 usec; Translate time 927 usec>
-verbose:Xclassdep
Traces all the class loading and the method and classnames with line numbers.
-version
Prints product version.
330 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
System property command-line options
Options that relate to the Garbage Collector are listed under “Garbage Collector
command-line options” on page 334.
-X
Prints help on nonstandard options.
332 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
System property command-line options
-Xnoaot
Turns off AOT support (JIT still loads).
-Xquickstart
Used for improving startup time of some Java applications. -Xquickstart causes
the JIT to run with a subset of optimizations; that is, a quick compile. This
quick compile allows for improved startup time. -Xquickstart is appropriate
for shorter running applications, especially those where execution time is not
concentrated into a small number of methods. -Xquickstart can degrade
performance if it is used on longer-running applications that contain hot
methods. The implementation of -Xquickstart is subject to change in future
releases.
334 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Garbage Collector command-line options
-Xmox<value>
Sets the maximum size of the old space.
-Xmo<value>
Sets both –Xmos and –Xmox.
-Xmns<value>
Sets the initial size of the new space. The minimum size is 4096 bytes.
-Xdisableexplicitgc
Disables system garbage collection
-Xverbosegclog:<path to file><filename>
Causes verboseGC output to be written to the specified file. If the file cannot
be found, verboseGC tries to create the file, and then continues as normal if it
is successful. If it cannot create the file (for example, if an invalid filename is
passed into the command), it will redirect the output to stderr.
-Xverbosegclog:<path to file><filename, X, Y>
Filename must contain a ″#″ (hash symbol), which is substituted with a
generation identifier, starting at 1. X and Y are integers. This option works
similarly to -Xverbosegclog:<path to file><filename>, but, in addition, the
verboseGC output is redirected to X files, each containing verboseGC output
from Y GC cycles.
Scavenger options
-Xmr<value>
Sets the remembered size setting
-Xmrx<value>
Sets the remembered maximum size setting
Compact options
default (no compaction option specified)
Makes the GC compact based on a series of triggers that attempt to compact
only when it is beneficial to the future performance of the JVM. No forced
compactions
-Xnocompactexplicitgc
Never runs compaction on system garbage collections. Compaction takes place
on global garbage collections if you specify -Xcompactgc or if compaction
triggers are met.
-Xcompactexplicitgc
Compacts on all system garbage collections. Compaction takes place on global
garbage collections if you specify -Xcompactgc specified or if compaction
triggers are met.
-Xcompactgc
Compacts on all garbage collections (system and global).
-Xnocompactgc
Disables compaction on all garbage collections (system or global).
Concurrent options
-Xgcpolicy:optthruput
Disables concurrent mark.
-Xgcpolicy:optavgpause
Enables concurrent mark.
Trace GC options
java -Xtgc:<arguments> MyClass
336 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Garbage Collector command-line options
backtrace
Before a garbage collection, a single line is printed containing the name of the
master thread for garbage collection, as well as the value of the osThread slot
in its J9VMThread structure.
compaction
Prints extra information showing the relative time spent by threads in the
″move″ and ″fixup″ phases of compaction
concurrent
Prints extra information showing the activity of the concurrent mark
background thread
dump
Prints a line of output for every free chunk of memory in the system, including
″dark matter″ (free chunks that are not on the free list for some reason, usually
because they are too small). Each line contains the base address and the size in
bytes of the chunk. If the chunk is followed in the heap by an object, the size
and class name of the object is also printed. Similar to terse.
freeList
Before a garbage collection, prints information about the free list and allocation
statistics since the last GC. Prints the number of items on the free list,
including ″deferred″ entries (with the scavenger, the unused space is a deferred
free list entry). For TLH and non-TLH allocations, prints the total number of
allocations, the average allocation size, and the total number of bytes discarded
in during allocation. For non-TLH allocations, also included is the average
number of entries that were searched before a sufficiently large entry was
found.
parallel
Produces statistics on the activity of the parallel threads during the mark and
sweep phases of a global GC.
references
Prints extra information every time a reference object is enqueued for
finalisation, showing the reference type, reference address, and referent
address.
scavenger
Prints extra information following each scavenger collection. A histogram is
produced showing the number of instances of each class (and their relative
ages) present in the survivor space. The space is linearly walked to achieve
this.
terse
Dumps the contents of the entire heap before and after a garbage collection.
For each object or free chunk in the heap, a line of trace output is produced.
Each line contains the base address, ″a″ if it is an allocated object, and ″f″ if it
is a free chunk, the size of the chunk in bytes, and if it is an object, its class
name.
338 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Appendix G. Default settings for the JVM
This appendix shows the default settings that the JVM uses; that is, how the JVM
operates if you do not apply any changes to its environment. The tables show the
JVM operation and the default setting.
The last column shows how the operation setting is affected and is set as follows:
v e – setting controlled by environment variable only
v c – setting controlled by command-line parameter or the IBM_JAVA_OPTIONS
environment variable
v ec– setting controlled by both (command-line always takes precedence) All the
settings are described elsewhere in this document. These tables are only a quick
reference to the JVM vanilla state
For default GC settings, see Chapter 2, “Understanding the Garbage Collector,” on
page 7.
Table 23. Cross platform defaults
JVM setting Default Setting
affected by
Javadumps Enabled ec
Javadumps on out of memory Enabled ec
Heapdumps Disabled ec
Heapdumps on out of memory Enabled ec
Sysdumps Enabled ec
Where dump files appear Current directory ec
Verbose output Disabled c
Boot classpath search Disabled c
JNI checks Disabled c
Remote debugging Disabled c
Strict conformancy checks Disabled c
Quickstart Disabled c
Remote debug info server Disabled c
Reduced signalling Disabled c
Signal handler chaining Enabled c
Classpath Not set ec
Accessibility support Enabled e
JIT Enabled ec
AOT compiler Enabled c
JIT debug options Disabled c
Java2D max size of fonts with algorithmic bold 14 point e
Java2D use rendered bitmaps in scalable fonts Enabled e
Java2D freetype font rasterizing Enabled e
Java2D use AWT fonts Disabled e
340 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Appendix H. Notices
This information was developed for products and services offered in the U.S.A.
IBM may not offer the products, services, or features discussed in this document in
other countries. Consult your local IBM representative for information on the
products and services currently available in your area. Any reference to an IBM
product, program, or service is not intended to state or imply that only that IBM
product, program, or service may be used. Any functionally equivalent product,
program, or service that does not infringe any IBM intellectual property right may
be used instead. However, it is the user’s responsibility to evaluate and verify the
operation of any non-IBM product, program, or service.
IBM may have patents or pending patent applications covering subject matter
described in this document. The furnishing of this document does not give you
any license to these patents. You can send license inquiries, in writing, to:
IBM Director of Licensing
IBM Corporation
North Castle Drive
Armonk, NY 10504-1785
U.S.A.
For license inquiries regarding double-byte (DBCS) information, contact the IBM
Intellectual Property Department in your country or send inquiries, in writing, to:
IBM World Trade Asia Corporation
Licensing
2-31 Roppongi 3-chome, Minato-ku
Tokyo 106-0032, Japan
The following paragraph does not apply to the United Kingdom or any other
country where such provisions are inconsistent with local law:
INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS
PUBLICATION “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS
FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or
implied warranties in certain transactions, therefore, this statement may not apply
to you.
Any references in this information to non-IBM Web sites are provided for
convenience only and do not in any manner serve as an endorsement of those Web
sites. The materials at those Web sites are not part of the materials for this IBM
product and use of those Web sites is at your own risk.
IBM may use or distribute any of the information you supply in any way it
believes appropriate without incurring any obligation to you.
Licensees of this program who wish to have information about it for the purpose
of enabling: (i) the exchange of information between independently created
programs and other programs (including this one) and (ii) the mutual use of the
information which has been exchanged, should contact IBM United Kingdom
Laboratories, MP146, Hursley Park, Winchester, Hampshire, SO21 2JN, United
Kingdom. Such information may be available, subject to appropriate terms and
conditions, including in some cases, payment of a fee.
The licensed program described in this information and all licensed material
available for it are provided by IBM under terms of the IBM Customer Agreement,
IBM International Program License Agreement, or any equivalent agreement
between us.
COPYRIGHT LICENSE:
Each copy or any portion of these sample programs or any derivative work, must
include a copyright notice as follows:
© (your company name) (year). Portions of this code are derived from IBM Corp.
Sample Programs. © Copyright IBM Corp. _enter the year or years_. All rights
reserved.
If you are viewing this information softcopy, the photographs and color
illustrations may not appear.
Trademarks
The following terms are trademarks or registered trademarks of International
Business Machines Corporation in the United States, or other countries, or both.
IBM WebSphere
z/OS OS/390
Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the
United States, other countries, or both.
342 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Trademarks
Microsoft, Windows, Windows NT, and the Windows logo are trademarks of
Microsoft Corporation in the United States, other countries, or both.
Other company, product and service names may be trademarks or service marks of
others.
346 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
client side, ORB 43 compaction phase (garbage collection) 8
getting hold of the remote object 44 detailed description 13
bootstrap process 45 compatibility tables
ORB initialization 44 WebSphere Application Server and JVM/SDK levels 313
remote method invocation 46 compilation failures, JIT 239
delegation 46 COMPLETED_MAYBE 169
servant 46 COMPLETED_NO 169
stub creation 43 COMPLETED_YES 169
client, ORB 173 completion status, ORB 169
clnt , AIX segment type 104 component dump (LOCKS), Javadump 195
cmd, AIX 102 concurrent mark (garbage collection) 12
codes, minor (CORBA) 321 connection handlers 72
collecting additional diagnostic data, Linux 139 console dumps 215
collecting data from a fault condition control flow optimizations (JIT) 30
AIX 125 conventions and terminology in book xiv
Linux 138 CORBA 33
collecting additional diagnostic data 139 client side interception points 52
core files 138 receive_exception (receiving reply) 52
determining the operating environment 139 receive_other (receiving reply) 52
proc file system 139 receive_reply (receiving reply) 52
producing Javadumps 138 send_poll (sending request) 52
sending information to Java Support 139 send_request (sending request) 52
strace, ltrace, and mtrace 140 examples 34
using system logs 139 fragmentation 51
Windows 150 further reading 34
z/OS 164 interfaces 34
com.ibm.CORBA.AcceptTimeout 40 interoperable naming service (INS) 54
com.ibm.CORBA.AllowUserInterrupt 40 Java IDL or RMI-IIOP, choosing 34
com.ibm.CORBA.BootstrapHost 40 Linux 141
com.ibm.CORBA.BootstrapPort 40 minor codes 321
com.ibm.CORBA.BufferSize 40 portable interceptors 51
com.ibm.CORBA.CommTrace 167 portable object adapter 49
com.ibm.CORBA.ConnectTimeout 40 remote object implementation or servant 35
com.ibm.CORBA.Debug 167 RMI and RMI-IIOP 33
com.ibm.CORBA.Debug.Output 167 RMI-IIOP limitations 34
com.ibm.CORBA.enableLocateRequest 41 server code 36
com.ibm.CORBA.FragmentSize 41 differences between RMI (JRMP) and RMI-IIOP 39
com.ibm.CORBA.FragmentTimeout 41 summary of differences in client development 39
com.ibm.CORBA.GIOPAddressingDisposition 41 summary of differences in server development 39
com.ibm.CORBA.InitialReferencesURL 41 server side interception points 52
com.ibm.CORBA.ListenerPort 41 receive_request (receiving request) 52
com.ibm.CORBA.LocalHost 41 receive_request_service_contexts (receiving request) 52
com.ibm.CORBA.LocateRequestTimeout 41, 174 send_exception (sending reply) 52
com.ibm.CORBA.MaxOpenConnections 41 send_other (sending reply) 52
com.ibm.CORBA.MinOpenConnections 41 send_reply (sending reply) 52
com.ibm.CORBA.NoLocalInterceptors 42 stub and ties generation 35
com.ibm.CORBA.ORBCharEncoding 42 CORBA GIOP message format 317
com.ibm.CORBA.ORBWCharDefault 42 cancel request header 319
com.ibm.CORBA.RequestTimeout 42, 174 fragment header 320
com.ibm.CORBA.SendingContextRunTimeSupported 40 fragment message 320
com.ibm.CORBA.SendVersionIdentifier 42 GIOP header 317
com.ibm.CORBA.ServerSocketQueueDepth 42 locate reply body 320
com.ibm.CORBA.ShortExceptionDetails 42 locate reply header 320
com.ibm.tools.rmic.iiop.Debug 42 locate request header 319
com.ibm.tools.rmic.iiop.SkipImports 42 reply body 319
comm trace , ORB 172 reply header 318
COMM_FAILURE 168 request body 318
command-line options 329 request header 318
class-loader 257 core dumps
garbage collector 334 Linux 129
general 329 core files
JIT 333 Linux 127
nonstandard 331 core files, Linux 138
system property 330 cp, AIX 102
command-line parameters, JVM CPU bottlenecks, AIX 120
cross-platform tools 190 CPU usage, Linux 136
commands, (IPCS), z/OS 152
Index 347
crashes debugging memory leaks, AIX (continued)
AIX 107 32-bit AIX Virtual Memory Model 112
Linux 134 64-bit AIX Virtual Memory Model 113
Windows 146 changing the Memory Model (32-bit JVM) 113
z/OS 153 fragmentation problems 117
documents to gather 153 Java heap exhaustion 117
failing function 154 Java or native heap exhausted 117
crashes, diagnosing Java2 32-Bit JVM default memory models 114
Windows monitoring the Java heap 116
sending data to IBM 147 monitoring the native heap 114
CreateThread, JVMRI 286 native and Java heaps 114
cross-platform tools native heap exhaustion 117
application trace 190 native heap usage 115
command-line parameters, JVM 190 receiving OutOfMemory errors 116
dump formatter 188 submitting a bug report 118
Heapdump 188 debugging memory leaks, Windows
Javacore 188 memory model 148
Javadump 188 tracing leaks 148
JPDA tools 189 debugging performance problem, AIX
JVM environment variables 190 application profiling 124
JVM trace 189 collecting data from a fault condition 125
JVMPI tools 188 CPU bottlenecks 120
JVMRI 189 finding the bottleneck 119
method trace 190 getting AIX technical support 125
I/O bottlenecks 124
JIT compilation 124
D JVM heap sizing 124
memory bottlenecks 123
data submission with problem report 85
debugging performance problems, AIX 119
javaserv (IBM internal only) 85
debugging performance problems, Linux
sending files to IBM support 86
CPU usage 136
data to be collected, ORB 177
JIT 138
DATA_CONVERSION 168
JVM performance 137
dbx Plug-in, AIX 106
memory usage 136
dbx, AIX 97
network problems 137
deadlocked hangs, z/OS 160
system performance 135
deadlocks 109, 193
debugging performance problems, Windows 149
deadlocks, Windows
data for bug report 149
debugging 147
frequently reported problems 150
debug properties, ORB 167
debugging techniques, AIX 97
com.ibm.CORBA.CommTrace 167
bindprocessor –q 97
com.ibm.CORBA.Debug 167
bootinfo 97
com.ibm.CORBA.Debug.Output 167
dbx 97
debugging commands
dbx Plug-in 106
AIX 97
debugging commands 97
bindprocessor –q 97
iostat 98
bootinfo 97
lsattr 98
dbx 97
netpmon 99
dbx Plug-in 106
netstat 100
iostat 98
nmon 101
lsattr 98
sar 103
netpmon 99
starting Heapdumps 97
netstat 100
starting Javadumps 97
nmon 101
topas 105
sar 103
tprof 105
topas 105
trace 105
tprof 105
truss 105
trace 105
vmstat 106
truss 105
debugging techniques, Linux
vmstat 106
ps command 129
Linux 130
vmstat command
debugging hangs, AIX 109
processes section 130
AIX deadlocks 109
debugging techniques, Windows 145
busy hangs 109
Dump Extractor 145
poor performance 111
Heapdumps 145
debugging hangs, Windows 147
Javadumps 145
debugging memory leaks, AIX
default memory models, Java2 32-Bit JVM (AIX) 114
32- and 64-bit JVMs 112
348 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
default settings, JVM 339 dump agents (continued)
delegation, ORB client side 46 heapdumps 216
deprecated Sun properties 42 help options 213
description string, ORB 170 Java dumps 216
Description, AIX segment type 104 removing 218
determining the operating environment, Linux 139 system dumps 215
df command, Linux 139 tool option 216
diagnosing crashes, AIX 107 triggering 214
documents to gather 107 types 214
locating the point of failure 108 using 213
diagnostic tools, ORB dump extraction
-J-Djavac.dump.stack=1 167 Windows 144
-Xtrace 167 dump extractor
diagnostics 185 Linux 128
diagnostics component 5 Dump Extractor
diagnostics options, JVM environment 326 Windows 145
diagnostics, class loader dump formatter 223
loading from native code 258 analyzing dumps 229
runtime 257 cross-platform tools 188
diagnostics, class-loader 257 example session 229
command-line options 257 problems to tackle with 224
diagnostics, overview 187 dump, generated (Javadump) 191
categorizing problems 187 dump, system monitor (JVM) 195
cross-platform tools 187 DumpDeregister, JVMRI 287
applications trace 190 DumpRegister, JVMRI 287
command-line parameters, JVM 190 dumps, setting up (z/OS) 152
dump formatter 188 dynamic verbosegc, JVMRI 287
Heapdump 188
Javadump (or Javacore) 188
JPDA tools 189
JVM environment variables 190
E
enabling full AIX core files 96
JVM trace 189
enabling trace at server startup, ORB 315
JVMPI tools 188
environment
JVMRI 189
checking on AIX 95
method trace 190
displaying current 323
platforms 187
JVM settings 323
differences between RMI (JRMP) and RMI-IIOP, ORB 39
basic JIT options 325
disabling the JIT 237
diagnostics options 326
Distributed Garbage Collection (DGC)
general options 324
RMI 72
Javadump and Heapdump options 325
documents to gather
setting up and checking on Windows 143, 144
AIX 107
setting up on Windows
z/OS 153
dump extraction 144
DTFJ
native tools 144
counting threads example 307
environment variables 323
diagnostics 303
JVM
interface diagram 305
cross-platform tools 190
overview 303
separating values in a list 323
working with a dump 303
setting 323
dump
z/OS 151, 326
events 209
environment, determining
initiation 209
Linux 139
overview 209
df command 139
JVM
free command 139
settings 210
lsof command 139
Linux 212
ps-ef command 139
platform-specific variations 211
top command 139
types 209
uname -a command 139
Windows 212
vmstat command 139
z/OS 211
error message IDs
dump (LOCKS component), Javadump 195
z/OS 153
dump agents
errors (OutOfMemory), receiving (AIX) 116
console dumps 215
Esid, AIX 104
default 217
example of real method trace 220
default settings 218
examples of method trace 220
examples 215
exceptions
filters 218
JNI 64
Index 349
exceptions, ORB 168 free command, Linux 139
completion status and minor codes 169 frequently reported problems, Windows 150
nested 171 frequently-asked questions
system 168 JIT 31
BAD_OPERATION 168 functions (table), JVMRI 286
BAD_PARAM 168
COMM_FAILURE 168
DATA_CONVERSION 168
MARSHAL 168
G
garbage collection 8
NO_IMPLEMENT 168
advanced diagnostics 249
UNKNOWN 168
-Xclassgc 250
user 168
-Xcompactexplicitgc 250
exhaustion of Java heap, AIX 117
-Xcompactgc 250
exhaustion of native heap, AIX 117
-Xdisableexplicitgc 249
explicit generation of a Heapdump 206
-Xgcthreads 250
external trace, JVMRI 294
-Xnoclassgc 250
-Xnocompactexplicitgc 250
-Xnocompactgc 250
F -Xtgc:backtrace 250
f, AIX 102 -Xtgc:compaction 251
failing function, z/OS 154 -Xtgc:concurrent 251
fault condition in AIX -Xtgc:dump 251
collecting data from 125 -Xtgc:excessiveGC 252
features, ORB 49 -Xtgc:freelist 252
client side interception points 52 -Xtgc:parallel 253
receive_exception (receiving reply) 52 -Xtgc:references 253
receive_other (receiving reply) 52 -Xtgc:scavenger 253
receive_reply (receiving reply) 52 -Xtgc:terse 254
send_poll (sending request) 52 TGC tracing 250
send_request (sending request) 52 allocation failures 243
fragmentation 51 allocation failures during concurrent mark 247
interoperable naming service (INS) 54 basic diagnostics (verbosegc) 242
portable interceptors 51 cache allocation 10
portable object adapter 49 coexisting with the Garbage Collector 18
server side interception points 52 bug reports 19
receive_request (receiving request) 52 finalizers 19
receive_request_service_contexts (receiving request) 52 finalizers and the garbage collection contract 20
send_exception (sending reply) 52 finalizers, summary 20
send_other (sending reply) 52 how finalizers are run 20
send_reply (sending reply) 52 manual invocation 20
file header, Javadump nature of finalizers 19
z/OS 198 summary 21
final section, Javadump thread local heap 18
z/OS 201 command-line options 334
finalizers 242 common causes of perceived leaks 241
floating stacks limitations, Linux 140 hash tables 242
font limitations, Linux 141 JNI references 242
font.properties file listeners 241
Linux font 180 objects with finalizers 242
Windows font 181 premature expectation 242
fonts static data 242
properties file 180 compaction phase 8
Linux font 180 detailed description 13
Windows font 181 concurrent mark 12, 246
fonts, NLS 179 concurrent kickoff 246
common problems 182 detailed description 10
installed 179 fine tuning options 17
properties 179 frequently asked questions 21
utilities 181 global collections 245
*.nix platforms 181 heap and native memory use by the JVM 254
Windows systems 181 large native objects 255
formatting, JVMRI 294 heap expansion 15
fragment header 320 heap lock allocation 10
fragment message 320 heap shrinkage 15
fragmentation heap size 8
AIX 117 problems 9
ORB 51, 166 how does it work? 241
350 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
garbage collection (continued) hangs (continued)
how to do heap sizing 16 z/OS (continued)
initial and maximum heap sizes 16 looping 160
interaction with applications 18 hangs, debugging
interaction with JNI 58 AIX 109
object references 58 AIX deadlocks 109
retained garbage 59 poor performance 111
JNI weak reference 15 Windows 147
mark phase 8 hash tables 242
detailed description 10 heap
mark stack overflow 11 expansion 15
parallel mark 11 shrinkage 15
memory allocation 9 heap (Java) exhaustion, AIX 117
native code 255 heap and native memory use by the JVM
nursery allocation failures 243 garbage collection
object allocation 7 large native objects 255
output from a System.gc() 242 heap and native memory use by the JVM, garbage
overview 7 collection 254
parallel bitwise sweep 13 heap lock 10
phantom reference 14 heap size
reachable objects 8 garbage collection 8
reference objects 14 problems 9
scavenger collections 245 heap sizing, garbage collection 16
soft reference 14 heap, verbose GC 208
sweep phase 8 Heapdump 205
detailed description 12 AIX, starting 97
System.gc() calls during concurrent mark 249 cross-platform tools 188
tenured allocation failures 244 enabling 205
understanding the Garbage Collector 7 explicit generation of 206
using verbosegc 17 Linux, starting 128
verbose, heap information 208 location of 207
weak reference 14 phd format 205
garbage collector previous releases 205
interaction with JNI summary 205
global references 59 triggered generation of 206
general debugging techniques, z/OS 152 using jdmpview 207
IPCS commands 152 Windows
GenerateHeapdump, JVMRI 288 starting 145
GenerateJavacore, JVMRI 288 heapdumps 216
generating a user dump file in a hang condition, heaps, native and Java
Windows 144 AIX 114
generation of a Heapdump how to read this book xiii
explicit 206 HPROF 297
location 207 output file 298
triggered 206 hung JVM
GetComponentDataArea, JVMRI 288 getting a dump from
GetRasInfo, JVMRI 288 Windows 147
getting a dump from a hung JVM, Windows 147
getting AIX technical support 125
getting files from IBM support 86
GIOP header 317
I
I/O bottlenecks, AIX 124
glibc limitations, Linux 140
InitiateSystemDump, JVMRI 289
global optimizations (JIT) 31
InjectOutOfMemory, JVMRI 289
global references (JNI) 64
InjectSigsegv, JVMRI 289
capacity 64
inlining (JIT) 30
INS, ORB
See interoperable naming service
H interceptors (portable), ORB 51
hanging, ORB 174 Interface Definition Language (IDL) 34
com.ibm.CORBA.LocateRequestTimeout 174 interoperable naming service (INS), ORB 54
com.ibm.CORBA.RequestTimeout 174 interpreter 6
hangs interpreting the stack trace, AIX 108
AIX Inuse, AIX segment type 104
busy hangs 109 iostat, AIX 98
z/OS 160 IPCS commands, z/OS 152
bad performance 161
deadlocked 160
Index 351
J JIT
command-line options 333
Java dumps 216 control flow optimizations 30
Java duty manager 77 frequently-asked questions 31
Java heap, AIX 114 global optimizations 31
exhaustion 117 how the JIT optimizes code 30
monitoring 116 inlining 30
Java Native Interface local optimizations 30
understanding 57 native code generation 31
Java or native heap exhausted, AIX 117 overview 29
Java service understanding 29
overview 77 JIT compilation
IBM service 77 AIX 124
Java duty manager 77 JIT compilation failures, identifying 239
submitting problem report to IBM 77 JIT options
Java Virtual Machine 187 JVM environment 325
JAVA_DUMP_OPTS 91, 210, 326 JIT problem determination 237
JAVA_LOCAL_TIME 327 disabling 237
JAVA_TDUMP_PATTERN=string 326 locating the failing method 238
JAVA_THREAD_MODEL 327 selectively disabling 237
Java2 32-Bit JVM default memory models, AIX 114 short-running applications 240
Java2 security permissions for the ORB 169 JIT problem, ORB 166
Javacore (cross-platform tools) 188 JIT, Linux 138
Javadump 191 JNI 57
classes, z/OS 201 checklist 68
classloaders 201 copying and pinning 60
cross-platform tools 188 debugging 67
enabling 191 exceptions 64
file header, title 198 garbage collection 15
final section generic use of isCopy and mode flags 66
z/OS 201 global references 64
interpreting 192 interaction with Garbage Collector 58
JVM system monitor dump 195 global references 59
location of generated dump 191 object references 58
LOCKS component dump 195 retained garbage 59
locks, monitors, and deadlocks (LOCKS) 193 isCopy flag 65
sample output local references 60
Linux 202 mode flag 65
Windows 202 problem determination 67
z/OS 196 synchronization 66
stack trace 199 understanding 57
storage management weak reference 15
z/OS 199 JNI references 242
system properties JPDA tools, cross-platform tools 189
z/OS 198 JVM
tags 193 API 5
threads, z/OS 199 application stack 4
triggering 192 building blocks 3
XHPI section 198 class loader 6
z/OS 198 diagnostics component 5
Javadumps interpreter 6
AIX 97 memory management 5
Linux 128 platform port layer 6
Windows 145 subcomponents 4
Javadumps, producing (Linux) 138 JVM dump initiation 209
jdmpview 223 Linux 212
commands 224 overview 209
general 224 platform-specific variations 211
heapdump 228 settings 210
memory analysis 226 Windows 212
trace 229 z/OS 211
working with classes 227 JVM heap sizing
working with objects 227 AIX 124
example session 229 JVM performance, Linux 137
jextract 223 JVM settings
what it is 223 environment 323
jextract 223 basic JIT options 325
352 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
JVM settings (continued)
environment (continued)
L
diagnostics options 326 large native objects
general options 324 heap and native memory use by the JVM
Javadump and Heapdump options 325 garbage collection 255
JVM system monitor dump 195 LE HEAP, z/OS 161
JVM trace, cross-platform tools 189 LE settings, z/OS 151
JVMPI 297 limitations, Linux 140
HPROF profiler 297 CORBA limitations 141
output file 298 floating stacks limitations 140
JVMPI tools, cross-platform tools 188 font limitations 141
JVMRI 283 glibc limitations 140
agent design 286 threads as processes 140
API calls 286 Linux
CreateThread 286 checking the system environment 134
DumpDeregister 287 collecting data from a fault condition 138
DumpRegister 287 collecting additional diagnostic data 139
dynamic verbosegc 287 core files 138
GenerateHeapdump 288 determining the operating environment 139
GenerateJavacore 288 proc file system 139
GetComponentDataArea 288 producing Javadumps 138
GetRasInfo 288 sending information to Java Support 139
InitiateSystemDump 289 strace, ltrace, and mtrace 140
InjectOutOfMemory 289 using system logs 139
InjectSigsegv 289 CORBA 141
NotifySignal 289 core files 127
ReleaseRasInfo 290 crashes, diagnosing 134
RunDumpRoutine 290 debugging commands 130
SetOutOfMemoryHook 290 gdb 131
TraceDeregister 290 ltrace tool 131
TraceRegister 291 mtrace tool 131
TraceResume 291 ps 130
TraceResumeThis 291 strace tool 131
TraceSet 291 tracing 131
TraceSnap 292 debugging hangs 135
TraceSuspend 292 debugging memory leaks 135
TraceSuspendThis 292 debugging performance problems 135
building the agent CPU usage 136
Linux 286 JIT 138
Windows 285 JVM performance 137
z/OS 286 memory usage 136
changing trace options 285 network problems 137
cross-platform tools 189 system performance 135
external trace 294 debugging techniques 128
formatting 294 finding out about the Java environment 134
functions (table) 286 gathering process information 134
launching the agent 285 Javadump sample output 202
RasInfo JVM dump initiation 212
request types 293 known limitations 140
structure 292 CORBA limitations 141
registering a trace listener 284 floating stacks limitations 140
writing an agent 283 font limitations 141
glibc limitations 140
threads as processes 140
ltrace 140
K mtrace 140
kernel, AIX segment type 104 nm command 129
known limitations, Linux 140 objdump command 129
CORBA limitations 141 problem determination 127
floating stacks limitations 140 ps command 129
font limitations 141 setting up and checking the environment 127
glibc limitations 140 starting heapdumps 128
threads as processes 140 starting Javadumps 128
strace 140
threading libraries 128
top command 129
tracing 131
using core dumps 129
Index 353
Linux (continued) memory leaks (continued)
using system logs 129 z/OS 161
using the dump extractor 128 LE HEAP 161
vmstat command 130 OutOfMemoryErrors 162
io section 130 virtual storage 161
memory section 130 memory leaks, debugging
processes section 130 AIX
swap section 130 32- and 64-bit JVMs 112
system section 130 32-bit AIX Virtual Memory Model 112
working directory 127 64-bit AIX Virtual Memory Model 113
Linux problem determination changing the Memory Model (32-bit JVM) 113
collecting data from a fault condition 138 Java heap exhaustion 117
core files 138 Java or native heap exhausted 117
determining the operating environment 139 Java2 32-Bit JVM default memory models 114
producing Javadumps 138 monitoring the Java heap 116
using system logs 139 monitoring the native heap 114
debugging performance problems native and Java heaps 114
CPU usage 136 native heap exhaustion 117
JIT 138 native heap usage 115
JVM performance 137 receiving OutOfMemory errors 116
memory usage 136 memory leaks, Windows
network problems 137 tracing 148
system performance 135 memory management 5
debugging techniques Memory Model (32-bit JVM), changing, AIX 113
ps command 129 memory model, Windows 148
known limitations 140 memory models, Java2 32-Bit JVM default (AIX) 114
CORBA limitations 141 memory usage, Linux 136
floating stacks limitations 140 memory usage, understanding
font limitations 141 AIX 111
glibc limitations 140 message format, CORBA GIOP 317
threads as processes 140 cancel request header 319
listeners 241 fragment header 320
local optimizations (JIT) 30 fragment message 320
local references (JNI) 60 GIOP header 317
capacity 63 locate reply body 320
manually handling 63 locate reply header 320
scope 60 locate request header 319
summary 63 reply body 319
locate reply body 320 reply header 318
locate reply header 320 request body 318
locate request header 319 request header 318
locating the failing method 238 message trace , ORB 171
location of generated Heapdump 207 method trace 219
LOCKS component dump, Javadump 195 advanced options 220
locks, monitors, and deadlocks (LOCKS), Javadump 193 cross-platform tools 190
looping hangs, z/OS 160 examples 220
lsattr, AIX 98 real example 220
lsof command, Linux 139 running with 219
ltrace, Linux 140 where output appears 220
minor codes , CORBA 321
minor codes, ORB 169
M mmap, AIX segment type 104
monitoring the Java heap, AIX 116
maintenance, z/OS 151
monitoring the native heap, AIX 114
MALLOCTYPE=watson 116
monitors, Javadump 193
mark phase (garbage collection) 8
monitors, registered (JVM system monitor dump) 195
concurrent mark 12
mtrace, Linux 140
detailed description 10
MustGather
parallel mark 11
collecting the correct data to solve problems 79
MARSHAL 168
memory allocation 9
cache allocation 10
heap lock allocation 10 N
memory bottlenecks, AIX 123 native code
memory leaks garbage collection 255
Windows native code generation (JIT) 31
classifying 148 native heap, AIX 114
debugging 147 exhaustion 117
354 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
native heap, AIX (continued) ORB (continued)
monitoring 114 CORBA (continued)
usage 115 RMI-IIOP limitations 34
native tools server code 36
Windows 144 stub and ties generation 35
nested exceptions, ORB 171 summary of differences in client development 39
netpmon, AIX 99 summary of differences in server development 39
netstat, AIX 100 debug properties 167
network problems, Linux 137 com.ibm.CORBA.CommTrace 167
NLS com.ibm.CORBA.Debug 167
font properties 179 com.ibm.CORBA.Debug.Output 167
font.properties file 180 debugging 165
Linux font 180 diagnostic tools
Windows font 181 -J-Djavac.dump.stack=1 167
fonts 179 -Xtrace 167
installed fonts 179 exceptions 168
problem determination 179 features 49
nmon, AIX 101 client side interception points 52
NO_IMPLEMENT 168 fragmentation 51
NotifySignal, JVMRI 289 interoperable naming service (INS) 54
portable interceptors 51
portable object adapter 49
O server side interception points 52
how it works 43
object allocation 7
identifying a problem 165
objects
fragmentation 166
reachable 8
JIT problem 166
objects with finalizers 242
ORB versions 166
objects, reference (garbage collection)
packaging 166
Garbage Collector interaction with JNI 58
platform-dependent problem 166
options
what the ORB component contains 165
command-line 329
what the ORB component does not contain 166
general 329
properties 40
nonstandard 331
RMI and RMI-IIOP
system property 330
differences between RMI (JRMP) and RMI-IIOP 39
JVM environment
examples 34
basic JIT 325
further reading 34
diagnostics 326
interfaces 34
general 324
introduction 33
method trace, advanced 220
remote object implementation or servant 35
options that control tracepoint selection 262
server code 36
options that indirectly affect tracepoint selection 263
stub and ties generation 35
ORB 33
summary of differences in client development 39
choosing Java IDL or RMI-IIOP 34
summary of differences in server development 39
client side 43
RMI-IIOP limitations 34
bootstrap process 45
security permissions 169
delegation 46
server side 47
getting hold of the remote object 44
processing a request 48
ORB initialization 44
servant binding 47
remote method invocation 46
servant implementation 47
servant 46
tie generation 47
stub creation 43
service: collecting data 176
common problems 174
data to be collected 177
client and server running, not naming service 175
preliminary tests 176
com.ibm.CORBA.LocateRequestTimeout 174
stack trace 170
com.ibm.CORBA.RequestTimeout 174
description string 170
hanging 174
nested exceptions 171
running the client with client unplugged 176
system exceptions 168
running the client without server 175
BAD_OPERATION 168
completion status and minor codes 169
BAD_PARAM 168
CORBA
COMM_FAILURE 168
differences between RMI (JRMP) and RMI-IIOP 39
DATA_CONVERSION 168
examples 34
MARSHAL 168
further reading 34
NO_IMPLEMENT 168
interfaces 34
UNKNOWN 168
introduction 33
traces 171
Java IDL or RMI-IIOP? 34
client or server 173
remote object implementation or servant 35
Index 355
ORB (continued) overview of diagnostics (continued)
traces (continued) cross-platform tools (continued)
comm 172 Heapdump 188
message 171 Javadump (or Javacore) 188
service contexts 173 JPDA tools 189
understanding JVM environment variables 190
client side interception points 52 JVM trace 189
features 49 JVMPI tools 188
fragmentation 51 JVMRI 189
how it works 43 method trace 190
interoperable naming service (INS) 54 platforms 187
portable interceptors 51
portable object adapter 49
processing a request 48
servant binding 47
P
packaging, ORB 166
servant implementation 47
parallel mark (garbage collection) 11
server side interception points 52
parameters
the client side 43
command-line
the server side 47
cross-platform tools, JVM 190
tie generation 47
parent-delegation model (class loader) 25
using 40
performance
user exceptions 168
factors 80
versions 166
questions to ask 81
ORB and WebSphere Application Server
performance problems, debugging
selecting ORB traces 316
AIX 119
tracing 315
application profiling 124
changing on a running server 316
collecting data from a fault condition 125
enabling at server startup 315
CPU bottlenecks 120
ORB component
finding the bottleneck 119
what it contains 165
getting AIX technical support 125
what it does not contain 166
I/O bottlenecks 124
ORB properties
JIT compilation 124
com.ibm.CORBA.AcceptTimeout 40
JVM heap sizing 124
com.ibm.CORBA.AllowUserInterrupt 40
memory bottlenecks 123
com.ibm.CORBA.BootstrapHost 40
Linux
com.ibm.CORBA.BootstrapPort 40
CPU usage 136
com.ibm.CORBA.BufferSize 40
JIT 138
com.ibm.CORBA.ConnectTimeout 40
JVM performance 137
com.ibm.CORBA.enableLocateRequest 41
memory usage 136
com.ibm.CORBA.FragmentSize 41
network problems 137
com.ibm.CORBA.FragmentTimeout 41
system performance 135
com.ibm.CORBA.GIOPAddressingDisposition 41
Windows 149
com.ibm.CORBA.InitialReferencesURL 41
data for bug report 149
com.ibm.CORBA.ListenerPort 41
frequently reported problems 150
com.ibm.CORBA.LocalHost 41
performance problems, z/OS 163
com.ibm.CORBA.LocateRequestTimeout 41
pers, AIX segment type 104
com.ibm.CORBA.MaxOpenConnections 41
Pgsp, AIX segment type 104
com.ibm.CORBA.MinOpenConnections 41
pid, AIX 101
com.ibm.CORBA.NoLocalInterceptors 42
Pin, AIX segment type 104
com.ibm.CORBA.ORBCharEncoding 42
platform-dependent problem, ORB 166
com.ibm.CORBA.ORBWCharDefault 42
platform-specific variations, JVM dump initiation 211
com.ibm.CORBA.RequestTimeout 42
platforms supported in diagnostics 187
com.ibm.CORBA.SendingContextRunTimeSupported 40
poor performance, AIX 111
com.ibm.CORBA.SendVersionIdentifier 42
portable interceptors, ORB 51
com.ibm.CORBA.ServerSocketQueueDepth 42
portable object adapter
com.ibm.CORBA.ShortExceptionDetails 42
ORB 49
com.ibm.tools.rmic.iiop.Debug 42
power management 260
com.ibm.tools.rmic.iiop.SkipImports 42
ppid, AIX 101
other sources of information xiv
preliminary tests for collecting data, ORB 176
OutOfMemory errors, receiving (AIX) 116
premature expectation 242
OutOfMemoryErrors, z/OS 162
pri, AIX 102
overview of diagnostics 187
private storage usage, z/OS 151
categorizing problems 187
problem determination
cross-platform tools 187
first steps 91
applications trace 190
Linux
command-line parameters, JVM 190
collecting additional diagnostic data 139
dump formatter 188
collecting data from a fault condition 138
356 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
problem determination (continued) problem determination (continued)
Linux (continued) z/OS (continued)
CORBA limitations 141 documents to gather 153
core files 138 environment variables 151
CPU usage 136 environment, checking 151
determining the operating environment 139 general debugging techniques 152
floating stacks limitations 140 IPCS commands 152
font limitations 141 LE settings 151
glibc limitations 140 maintenance 151
JIT 138 OutOfMemoryErrors 162
JVM performance 137 private storage usage 151
known limitations 140 process deadlocked 160
memory usage 136 process looping 160
network problems 137 setting up dumps 152
proc file system 139 TDUMPs 155
producing Javadumps 138 virtual storage 161
ps command 129 problem determination, JIT 237
sending information to Java Support 139 disabling the JIT 237
strace, ltrace, and mtrace 140 locating the failing method 238
system performance 135 selectively disabling the JIT 237
threads as processes 140 short-running applications 240
using system logs 139 problem report
ORB 165 advice 83
collecting data 176 before you submit 79
common problems 174 checklist 79
debug properties 167 contents 83
fragmentation 166 data to include 79
identifying the problem 165 escalating problem severity 84
interpreting ORB traces 171 factors that affect JVM performance 80
interpreting the stack trace 170 getting files from IBM support 86
JIT problem 166 overview 77
ORB exceptions 168 IBM service 77
ORB versions 166 Java duty manager 77
packaging 166 performance problem questions 81
platform-dependent problem 166 problem severity ratings 83
what ORB contains 165 submitting data 85
what ORB does not contain 166 javaserv (IBM internal only) 85
Windows 143 sending files to IBM support 86
analyzing deadlocks 147 using your own ftp server 87
classifying leaks 148 submitting to IBM service 77
collecting data from a fault condition 150 test cases 80
data for bug report 149 when you will receive your fix 87
debugging hangs 147 problem severity ratings 83
debugging memory leaks 147 escalating 84
debugging performance problems 149 problem submission
debugging techniques 145 advice 83
diagnosing crashes 146 data 85
Dump Extractor 145 javaserv (IBM internal only) 85
frequently reported problems 150 sending files to IBM support 86
getting a dump from a hung JVM 147 using your own ftp server 87
Heapdumps 145 escalating problem severity 84
Javadumps 145 getting files from IBM support 86
memory model 148 overview 77
native tools 144 IBM service 77
sending data to IBM 147 Java duty manager 77
setting up and checking environment 143, 144 problem severity ratings 83
setting up for dump extraction 144 raising a report 83
tracing leaks 148 sending to IBM service 77
z/OS when you will receive your fix 87
allocations to LE HEAP 161 problems, frequently reported (Windows) 150
badly-performing process 161 problems, ORB 174
collecting data 164 hanging 174
debugging hangs 160 proc file system, Linux 139
debugging memory leaks 161 process private, AIX segment type 104
debugging performance problems 163 processes section, vmstat command 130
determining the failing function 154 producing Javadumps, Linux 138
diagnosing crashes 153 properties, ORB 40
Index 357
properties, ORB (continued) ReportEnv (continued)
com.ibm.CORBA.AcceptTimeout 40 Windows 143
com.ibm.CORBA.AllowUserInterrupt 40 reporting problems in the JVM, summary xiv
com.ibm.CORBA.BootstrapHost 40 request body 318
com.ibm.CORBA.BootstrapPort 40 request header 318
com.ibm.CORBA.BufferSize 40 request types, JVMRI (RasInfo) 293
com.ibm.CORBA.ConnectTimeout 40 RMI 71
com.ibm.CORBA.enableLocateRequest 41 debugging applications 73
com.ibm.CORBA.FragmentSize 41 Distributed Garbage Collection (DGC) 72
com.ibm.CORBA.FragmentTimeout 41 examples 34
com.ibm.CORBA.GIOPAddressingDisposition 41 further reading 34
com.ibm.CORBA.InitialReferencesURL 41 implementation 71
com.ibm.CORBA.ListenerPort 41 interfaces 34
com.ibm.CORBA.LocalHost 41 introduction 33
com.ibm.CORBA.LocateRequestTimeout 41 remote object implementation or servant 35
com.ibm.CORBA.MaxOpenConnections 41 server code 36
com.ibm.CORBA.MinOpenConnections 41 differences between RMI (JRMP) and RMI-IIOP 39
com.ibm.CORBA.NoLocalInterceptors 42 summary of differences in client development 39
com.ibm.CORBA.ORBCharEncoding 42 summary of differences in server development 39
com.ibm.CORBA.ORBWCharDefault 42 stub and ties generation 35
com.ibm.CORBA.RequestTimeout 42 thread pooling 72
com.ibm.CORBA.SendingContextRunTimeSupported 40 RMI-IIOP
com.ibm.CORBA.SendVersionIdentifier 42 choosing against Java IDL 34
com.ibm.CORBA.ServerSocketQueueDepth 42 examples 34
com.ibm.CORBA.ShortExceptionDetails 42 further reading 34
com.ibm.tools.rmic.iiop.Debug 42 interfaces 34
com.ibm.tools.rmic.iiop.SkipImports 42 introduction 33
properties, system (Javadump), z/OS 198 limitations 34
ps command remote object implementation or servant 35
AIX 101 server code 36
Linux 129 differences between RMI (JRMP) and RMI-IIOP 39
ps-ef command, Linux 139 summary of differences in client development 39
summary of differences in server development 39
stub and ties generation 35
R RunDumpRoutine, JVMRI 290
runtime diagnostics, class loader 257
raising a problem report for submission 77
contents 83
escalating problem severity 84
problem severity ratings 83 S
RAS interface (JVMRI) 283 sample output, Javadump
RasInfo, JVMRI Linux 202
request types 293 z/OS 196
structure 292 sar, AIX 103
receive_exception (receiving reply) 52 sc, AIX 102
receive_other (receiving reply) 52 selecting ORB traces 316
receive_reply (receiving reply) 52 selectively disabling the JIT 237
receive_request (receiving request) 52 send_exception (sending reply) 52
receive_request_service_contexts (receiving request) 52 send_other (sending reply) 52
receiving OutOfMemory errors, AIX 116 send_poll (sending request) 52
reference objects (garbage collection) 14 send_reply (sending reply) 52
registered monitors send_request (sending request) 52
JVM system monitor dump 195 sending data to IBM, Windows 147
ReleaseRasInfo, JVMRI 290 sending files to IBM support
reliability, availability, and serviceability interface IBM internal only 85
(JVMRI) 283 outside IBM 86
Remote Method Invocation using your own ftp server 87
See RMI 71 sending information to Java Support, Linux 139
remote object servant, ORB client side 46
ORB client side server code, ORB 36
bootstrap process 45 server side interception points, ORB 52
getting hold of 44 receive_request (receiving request) 52
remote method invocation 46 receive_request_service_contexts (receiving request) 52
remote object implementation or servant, ORB 35 send_exception (sending reply) 52
reply body 319 send_other (sending reply) 52
reply header 318 send_reply (sending reply) 52
ReportEnv server side, ORB 47
AIX 95, 127 processing a request 48
358 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
server side, ORB (continued) system exceptions, ORB (continued)
servant binding 47 BAD_PARAM 168
servant implementation 47 COMM_FAILURE 168
tie generation 47 DATA_CONVERSION 168
server, ORB 173 MARSHAL 168
service contexts, ORB 173 NO_IMPLEMENT 168
service: collecting data, ORB 176 UNKNOWN 168
data to be collected 177 system logs 129
preliminary tests 176 system logs, using (Linux) 139
SetOutOfMemoryHook, JVMRI 290 system monitor dump, JVM 195
setting up and checking AIX environment 95 system performance, Linux 135
setting up and checking environment, Windows 143, 144 system properties
setting up for dump extraction command-line options 330
Windows 144 system properties, Javadump
settings, default (JVM) 339 z/OS 198
settings, JVM System.gc() 242, 249
environment 323
basic JIT options 325
diagnostics options 326
general options 324
T
tags, Javadump 193
Javadump and Heapdump options 325
tat, AIX 103
settings, JVM dump initiation 210
TDUMPs
severity ratings for problems 83
z/OS 155
escalating 84
technical support for AIX 125
shared library, AIX segment type 104
terminology and conventions in this book xiv
shmat/mmap, AIX segment type 104
test cases 80
signal information, Javadump
TGC tracing
z/OS 198
garbage collection 250
skeletons, ORB 35
thread pooling
st, AIX 102
RMI 72
stack trace, interpreting (AIX) 108
threading libraries 128
stack trace, Javadump
threads and stack trace, Javadump
z/OS 199
z/OS 199
stack trace, ORB 170
threads as processes, Linux 140
description string 170
tid, AIX 102
nested exceptions 171
time, AIX 102
static data 242
tool option for dumps 216
stime, AIX 102
tools
storage management, Javadump
cross-platform 187
z/OS 199
platform-specific 190
storage usage, private (z/OS) 151
tools, native
storage, z/OS 161
Windows 144
strace, Linux 140
tools, ReportEnv
string (description), ORB 170
AIX 95, 127
stub and ties generation, ORB 35
Windows 143
submitting a bug report, AIX 118
top command, Linux 139
submitting data
topas, AIX 105
javaserv (IBM internal only) 85
tprof, AIX 105
sending files to IBM support 86
trace
submitting data with a problem report 85
AIX 105
javaserv (IBM internal only) 85
application trace 277
sending files to IBM support 86
applications 259
using your own ftp server 87
controlling 261
summary of differences in client development 39
internal 260
summary of differences in server development 39
Java applications and the JVM 259
Sun properties, deprecated 42
methods 259
svmon, AIX 103
MiscellaneousTrace control options 264
sweep phase (garbage collection) 8
option summary 262
detailed description 12
options
parallel bitwise sweep 13
applids 263, 265
synchronization
buffers 264, 265
JNI 66
count 265
system dump
detailed descriptions 264
Windows 145
exception 265
system dumps 215
exception.output 263, 271
system exceptions, ORB 168
external 265
BAD_OPERATION 168
iprint 265
Index 359
trace (continued) truss, AIX 105
options (continued) tty, AIX 102
maximal 262, 265 Type, AIX 104
methods 263, 269 clnt 104
minimal 262, 265 Description parameter 104
output 263, 270 mmap 104
print 265 pers 104
properties 264 work 104
resume 263, 273
resumecount 263, 273
specifying 262
state.output 263, 271
U
uid, AIX 101
summary 262
uname -a command, Linux 139
suspend 263, 272
understanding memory usage, AIX 111
suspendcount 263, 273
understanding the class loader 25
trigger 263, 273
UNKNOWN 168
options that control tracepoint selection 262
user dumps
options that specify output files 263
generating in hang condition 144
placing data into a file 261
user exceptions, ORB 168
external tracing 261
user, AIX 102
trace combinations 261
using dump agents 213
tracing to stderr 261
using system logs, Linux 139
placing data into in-storage buffers 260
utilities
snapping buffers 260
NLS fonts 181
power management effect on timers 260
*.nix platforms 181
properties file 276
Windows systems 181
trace formatter 275
invoking 275
tracepoint ID 276
triggering and suspend or resume 263 V
trace data, JVMRI versions, ORB 166
intercepting 293 virtual storage, z/OS 161
trace formatter 275 vmstat command, Linux 139
invoking 275 processes section 130
trace listener, registering (JVMRI) 284 vmstat, AIX 106
trace options Vsid, AIX 104
options that indirectly affect tracepoint selection 263
trace options, changing (JVMRI) 285
trace, external (JVMRI) 294
TraceDeregister, JVMRI 290
W
WebSphere Application Server
tracepoint specification 267
environment, working in 93
TraceRegister, JVMRI 291
WebSphere Application Server and ORB
TraceResume, JVMRI 291
selecting ORB traces 316
TraceResumeThis, JVMRI 291
tracing 315
traces, ORB 171
changing on a running server 316
client or server 173
enabling at server startup 315
comm 172
when you will receive your fix, problem report 87
message 171
who should read this book xiii
service contexts 173
Windows
TraceSet, JVMRI 291
analyzing deadlocks 147
TraceSnap, JVMRI 292
classifying leaks 148
TraceSuspend, JVMRI 292
collecting data 150
TraceSuspendThis, JVMRI 292
collecting data from a fault condition 150
tracing
deadlocks 147
Linux 131
debugging hangs 147
ltrace tool 131
analyzing deadlocks 147
mtrace tool 131
debugging memory leaks 147
strace tool 131
classifying leaks 148
ORB and WebSphere Application Server 315
memory model 148
changing on a running server 316
tracing leaks 148
enabling at server startup 315
debugging performance problems 149
selecting ORB traces 316
data for bug report 149
tracing leaks, Windows 148
frequently reported problems 150
transaction dumps
debugging techniques 145
z/OS 155
diagnosing crashes 146
triggered generation of a Heapdump 206
sending data to IBM 147
triggering dumps 214
Dump Extractor 145
360 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms
Windows (continued)
frequently reported problems 150
generating a user dump file in a hang condition 144
getting a dump from a hung JVM 147
hangs
getting a dump 147
Heapdumps 145
Javadump sample output 202
Javadumps 145
JVM dump initiation 212
memory model 148
native tools 144
problem determination 143
sending data to IBM 147
setting up and checking environment 143, 144
setting up for data collection 144
dump extraction 144
native Windows tools 144
setting up for dump extraction 144
system dump 145
tracing leaks 148
Windows systems
font utilities 181
work, AIX segment type 104
X
XHPI section, Javadump
z/OS 198
Z
z/OS
collecting data 164
crashes 153
documents to gather 153
failing function 154
environment variables 151, 326
environment, checking 151
error message IDs 153
general debugging techniques 152
IPCS commands 152
hangs 160
bad performance 161
deadlocked 160
looping 160
Javadump sample output 196
JVM dump initiation 211
LE settings 151
maintenance 151
memory leaks 161
LE HEAP 161
OutOfMemoryErrors 162
virtual storage 161
performance problems 163
private storage usage 151
problem determination
environment, checking 151
setting up dumps 152
TDUMPs 155
Index 361
362 Java 2 Technology Edition Version 1.4.2 Diagnostics Guide for z/OS64 and AMD64 platforms