Problem determination and debugging
In this chapter, we describe some tools and techniques that can help you discover and fix problems in your application or configuration.
In the first section, we describe some of the tools and techniques for problem determination. In this section, we summarize the most common problems and the source of information that can help you identify and solve the problems. We introduce some facilities that system programmers are familiar with, including varies of dumps, traces, and the tools that can help to analyze them.
In the second section, we describe using Rational Developer for System z to perform interactive debugging to help an application developer find and correct problems in the Java application quickly and easily.
8.1 Debugging and problem determination
There are times when your CICS Java application does not display the expected or desired behavior. Your application might:
Not start at all.
Produce incorrect output.
Enter a loop.
Wait indefinitely for another resource.
Perform badly.
Result in a system message, abend, or dump.
There might be a problem with the application itself that you can discover and correct yourself. The configuration can be in error, which prevents the application from executing correctly. Fixing the configuration allows the application to execute as expected.
We discuss some tools and techniques to help you resolve these issues.
You might encounter a problem with the SDK, Language Environment, or CICS, which requires assistance from IBM to resolve. One aim of this section is to describe how to gather the documentation that IBM is likely to require and how to identify which area of IBM support is required.
CICS provides an extensive set of problem determination aids for systems and application programmers. Many of the usual sources of CICS diagnostic information, such as abend codes, error messages, dumps, and trace, are useful in resolving a CICS Java problem.
However, there are extra considerations when diagnosing a problem in a CICS Java application. Because of the nature of the JVM, you might need to look at diagnostic information from UNIX System Services, Language Environment, and IBM SDK for z/OS.
The following Web site contains useful hints and tips for IBM SDK for z/OS problem solving. You can use the information at this site along with other sources of information, such as this IBM Redbooks publication and CICS Problem Determination Guide, SC34-6239, to develop a strategy for carrying out problem determination for CICS Java applications.
The JVMs own diagnostic tools and interfaces that give you detailed information about what is happening within the JVM than CICS can because CICS is unaware of many of the activities within a JVM. You can download the diagnostics guide for the IBM SDK from the following Web site:
8.1.1 First considerations
Before looking in detail at some of the diagnostic tools, we describe some points you must consider if you encounter a problem with CICS Java. There might be a straightforward explanation for the problem, for example, the wrong JVM profile or properties file might have changed or a typing error might have occurred when entering a path to a file or directory. You can save a lot of time by carrying out these initial checks.
Which version of Java are you using
IBM provides regular service updates to the SDK. We recommend that you install the latest service level to take advantage of improved service, performance, and stability. More information about the PTF numbers, build date, and availability are on the Java Service Summary Web site:
Table 8-1 shows parts of the SDK 5 service releases at the time of writing.
Table 8-1 SDK 5 service releases
Service release
PTF number
Build date
SR8a
UK39047
August. 11, 2008
SR8
UK38281
July.10, 2008
SR7
UK34636
March.15, 2008
 
Tip: The system property java.full version tells you the build level of the SDK you are using, which is written to the event log along with the other system properties if event logging is enabled.
If you specify the system property com.ibm.cics.showJavaVersion=true, CICS writes message DFHSJ0901 to CSMT when the JVM initializes. The message text contains the Java version (including the build date) used for that invocation of the JVM.
Is the JVM failing to start
Is the JVM failing to start:
Does the RACF profile for the CICS region user ID have an OMVS segment?
Does the directory specified for WORK_DIR exist and does the CICS region user ID have read and write permissions to it?
Are the path names to the Java directory correct and in sync on the JAVA_HOME and LIBPATH options?
Does the CICS region user ID have read permission to all directories on the path?
Is the value specified for the CICS_DIRECTORY correct?
Which JVM mode is in use
Which JVM mode is in use:
Is the JVM using the expected JVM profile?
Is the JVM running in continuous mode?
Is the JVM using the Shared Class Cache?
Is the JVM running in the correct key (CICS or USER)?
Has the JVM abended
If you see the following message in the CICS log, the JVM (or some native code running under the JVM) abended, but all CICS knows is that the call to CEEPIPI returned an error code.
DFHSJ0203 A call to CEEPIPI with function code CALL_SUB has
failed. (Return code was - X’0000001C’)
You will require assistance from IBM in resolving this type of problem. You must gather any diagnostics that the JVM produces. There might be a JAVADUMP in the working directory.
8.2 Common problems
In this section, we provide some common error messages that you are likely to encounter.
8.2.1 Abend AJ04
You receive abend AJ04 when CICS cannot find your program’s main method. This is a common error. Example 8-1 shows an example of an abend AJ04.
Example 8-1 Most common abend AJ04
DFHAC2206 04:25:32 A6POC3C4 Transaction HELO failed with abend AJ04. Updates to local recoverable resources backed out.
The abend AJ04 is typically caused by:
Check the name of the main class on the program definition (CEMT INQUIRE PROGRAM) and make sure that it is spelled correctly.
Double-check the main class name. It is easy to miss a typo.
Check the classpath settings in the JVM profile.
Make sure your program definition uses the correct JVM profile.
Check that your main class does actually have a public static void main(String []) or public static void main(CommAreaHolder) method.
Make sure CICS has access to the directories and files in the classpath.
When deploying the Java bytecode to the mainframe, make sure it is transmitted in binary mode. FTP and Rational Developer for System z can perform character set conversions if the default setting is overridden. Make sure no such conversion takes place for .class and .jar files; otherwise, you will probably see the message, in Example 8-2, in the log.
Example 8-2 Bad magic number is usually caused by improper conversion during the transmission
DFHSJ0904 11/12/2008 04:14:54 A6POC3C4 CICSUSER E011 HELO HELOPROG Exception java.lang.ClassFormatError:
(com/ibm/itso/sg245275/HelloWorld) bad magic number at offset=0 occurred creating object reference for class com.ibm.itso.sg245275.HelloWorld.
DFHDU0203I 11/12/2008 04:14:54 A6POC3C4 A transaction dump was taken for dumpcode: AJ04, Dumpid: 1/0003.
DFHAC2236 11/12/2008 04:14:55 A6POC3C4 Transaction HELO abend AJ04 in program HELOPROG term E011. Updates to local recoverable resources will be backed out.
When using file system export from Rational Developer for System z, it is a common mistake to use the “Create directory structure for files” and “Create only selected directories” options inconsistently (especially when using the latter). Check that your .class files ended up on the zFS file system where you want them.
8.2.2 Incorrect output or behavior
It is also normal to find out that your program is not generating expected messages or behavior. In this case, the reason can vary. You might need to check the stdout and stderr to see if any exception is thrown by your problem. If there is nothing obvious in the log, you might need to turn on the trace or take some dump to analyze the detail reason. Or you might want to try to debug your program interactively to see what is happening. See 8.4, “Interactive debugging” on page 212 for details.
8.2.3 No response
In this case, your program might loop infinitely or wait for some resource to become available, possibly a deadlock. Usually the infinite looping takes up high CPU times although the resource wait and deadlock takes up almost no CPU time at all. You can distinguish it by looking at the CPU time of the CICS region.
In the case of deadlocks, you probably need to use the Javadump tool to diagnose the lock status and the resources that cause the deadlock. We explain it later.
If the programing is in infinite looping, you can analyze what the thread is doing by taking a console-initiated dump (SVC dump), then use the dump viewer to see what is happening and why it loops infinitely. See more detail in SDK DIagnostics Guide, SC34-6650.
8.2.4 OutOfMemoryError
There are chances that your application reports OutOfMemoryError exception. Typically the JVM reports this error when the heap storage is exhausted and cannot allocate new objects, or when a JVM’s attempt to call malloc() is failed. The possible causes are:
Insufficient heap size: Your application might need more memory than defined.
The program design problem: There might be some memory leak.
JVM fails to get more memory by malloc().
If it is because the program requires more memory than defined, using the parameter -Xmx in the JVM profile, you must increase the maximum heap size to solve this problem.
Java uses references to keep track of the live objects in memory. An Object with at least one reference to it from a live thread or a static value is considered a live object and is not removed from memory during a garbage collection cycle.
To make an object eligible for garbage collection, the reference to that object must be set to null or must be out of scope. It is not necessary to explicitly set every reference to null, so for example, an object referenced only by a method local variable becomes eligible for garbage collection when the method ends and the variable goes out of scope, but memory leaks are caused by failure to remove references to unused objects. If you are in doubt about whether an object reference is causing a memory leak, it is always safer to set that reference to null after it is no longer required. Failing to remove references to objects that are no longer required results in unnecessary objects that take up more and more heap and finally cause an OutOfMemoryError exception to occur when the heap fills.
If it is that JVM calls to malloc() failed, you will likely get an associated error code. In this case, you can use the following useful rules to estimate the spaces required.
Since EDSALIM + MVS STORAGE = REGION SIZE
REGION SIZE is defined in CICS JCL (allocated up front)
EDSALIM is SIT parameter in CICS JCL (allocated up front)
MVS STORAGE is used for JVMs (allocated when required)
Max no. of JVMs in a region set using MAXJVMTCBS SIT parameter
Size of JVM approx 25Mb* + Xmx (Xmx is max JVM heap size set in DFHJVMPR)
Now do the maths:
If EDSALIM + (MAXJVMTCBS * (25Mb + Xmx)) > REGION SIZE,
then Java may run out of storage.
To solve the OutOfMemoryError problem, first identify if it is the configuration problem or the application design problem. If it is due to the wrong configuration, just increase the maximum heap size in the JVM profile to solve the problem. If it is the application design problem, you probably need to:
Review your code and correct the way for managing the object collections
Enable the heapdump to analyze what is in the heap when the error occurred, which helps you to identify the problem quickly, which we explain in 8.3.2, “Heapdump” on page 203.
Switch on -verbose:gc output, which causes the JVM to print out a message before and after a garbage collection cycle. If the total available space on the heap decreases overtime after each GC cycle, there must be some object leak. See more detail in 8.3.3, “Monitoring garbage collection cycles” on page 204.
8.2.5 Performance is not good
The performance problem is always difficult to solve. Here are some possible aspects that might affect the performance of the application:
Insufficient CPU power, memory, or I/O capability
Improper configuration for the heap size
Using Just-In-Time (JIT) compilation
Application design problems, for example, poor algorithms, and so on
Chapter 5, “Writing Java 5 applications for CICS” on page 75 offers some general guidance that can help you to avoid some application performance issues.'
Your program might still run slowly even if you do extensive tuning. The hardware environment is still not enough to handle the workload of your application. The only way to solve it is to perform a hardware upgrade to remove the bottleneck.
A poorly chosen of the heap size can also cause the degrade of the performance because the increasing frequency of the garbage collection cycle adds considerable overhead to the system, which might affect your application. To know how often the garbage collection occur, So it is important to select a optimized heap size for your JVM. To see how to select a proper heap size for your program, refer to Chapter 2 How to do heap sizing in SDK DIagnostics Guide, SC34-6650.
Use of Just-In-Time compiler can increase the performance of the application. JIT compiler compiles selected methods bytecode to native machine code to avoid the process of interpreting the bytecodes each time it runs, which allow the speed of Java program to approach that of a native program. The JIT compiler is enabled by default, you might want to review the configuration if you hit some performance problem.
You can learn a lot about your Java application by using the HPROF profiling agent to identify if it is the design lead to a poor performance. HPROF is a demonstration profiler that is shipped with the IBM SDK that uses the JVMTI to collect and record information about Java execution. Use it to work out which parts of a program are using the most memory or processor time. For more information about HPROF, refer to the following Web site:
8.2.6 Problems caused by static values in continuous JVMs
Static values in Java programs persist between uses of the JVM where a continuous JVM is used. If these values are changed by one transaction that is running in the JVM, subsequent transactions running in that JVM pick up this modified value. These problems are difficult to recreate in test environments because of the interaction of different programs running in the JVM. Guidance on how to avoid these problems is in 2.3.2, “Continuous JVM” on page 21. The CICS JVM Application Isolation Utility tool that is provided with CICS can help you to check your usage of static fields and classes, which helps you identify these problems, and we describe this tool in 2.4, “Analyzing programs for use in a continuous JVM” on page 23.
8.3 Where to look for diagnostic information
You can look in many places to gather all of the diagnostic information to solve a problem. The various components that are required to provide CICS Java support writes diagnostics to different locations.
You might find diagnostic information in familiar places:
MVS console messages
CICS messages written to TD queues or terminal end user
CICS transaction abend codes
CICS trace
You can use standard problem determination techniques in this case, for example, you can look in CICS Messages And Codes, GC34-6442, for an explanation of a CICS message or transaction abend code. A suggested course of action that you can take to resolve the problem might also be included with the explanation. However, for a fault in the JVM you must inspect additional diagnostic information. You can get some of this information by default; however, you might have to specify JVM options to obtain the information you need to resolve a problem.
The extra information can come from any of these items:
Java stack traces when exceptions are thrown
Javadumps:
 – Transaction dump: An unformatted dump requested by the MVS IEATDUMP service. You can post-process this dump with Interactive Problem Control System (IPCS).
 – CEEDUMP: Formatted application level dump, requested by the Language Environment service CEE3DMP.
 – JAVADUMP: Formatted internal state data produced by the IBM JVM.
Heapdump: JVM generates a heap dump when the heap is exhausted or by user request. It contains all of the live objects in the heap when the dump is taken
Debugging messages written to stderr or stdout (for example, the output from the JVM when switches, such as -verbose:gc, -verbose, or -Xtgc are used)
Binary or formatted trace data from the JVM internal high-performance trace
SVC dumps that the MVS Console DUMP command obtains (typically for loops or hangs)
Trace data from other products or components (for example, Language Environment traces or the Component trace for z/OS UNIX)
In the next sections, we provide more information about the diagnostics that might not be familiar to those of you who are from a traditional CICS background.
8.3.1 Javadumps
The JVM has code to create Javadumps when the JVM terminates or crashes unexpectedly. You can control the code by using environment variables and runtime switches. A Javadump is a file that attempts to summarize the state of the JVM at the instant the signal occurred.
The crash might be the result of an error in JVM code or JNI code. If the error is in JVM code or JNI code supplied by IBM, you must contact IBM for assistance. The information in this section helps you to identify the source of the error and to gather the correct documentation for IBM support.
On z/OS, you control the behavior of the Javadump using the JAVA_DUMP_OPTS environment variable. You can specify this variable in your JVM profile.
If you do not specify JAVA_DUMP_OPTS in your profile, CICS uses the following default:
JAVA_DUMP_OPTS=”ONANYSIGNAL(JAVADUMP,CEEDUMP,SYSDUMP),ONINTERRUPT(NONE)”
If a CICS JVM crashes, you receive a formatted Javadump, a Language Environment dump, and an unformatted transaction dump.
You can find the full syntax for JAVA_DUMP_OPTS on z/OS in SDK DIagnostics Guide, SC34-6358. You should not need to change the dump options unless advised to do so by IBM support.
If the JVM crashes, a JAVADUMP, Language Environment CEEDUMP and Java transaction dump is produced. Any one of the dumps produced might be enough on its own to find the cause of the problem.
JAVADUMP
A JAVADUMP is a formatted text file that provides information about the JVM at the time of the failure. The JVM checks each of the following locations for existence and write-permission and stores the Javadump in the first one available. You must have enough free disk space (possibly up to 2.5 MB) for the Javadump file to be written correctly:
The location specified by the _CEE_DMPTARG environment variable, if set
The current working directory of the JVM processes
The location specified by the TMPDIR environment variable, if set
The /tmp directory
The file name is JAVADUMP.yyyymmdd.hhmmss.&PID.txt, where PID is the process ID (for example, JAVADUMP.20050330.074905.txt).
Each line of the JAVADUMP starts with a tag. You can use this tag to parse the JAVADUMP.
There is a lot of information contained in a JAVADUMP. There is more information about interpreting a JAVADUMP in SDK DIagnostics Guide, SC34-6358. We provide some of the information that you can use to obtain from the JAVADUMP here.
At the top of the file is information, such as:
The date and time of the dump
The build level of the SDK
The OS level
The signal that caused the dump to be taken (In Example 8-3 on page 201, a SIGSEGV (signal 11) was received.)
Example 8-3 on page 201 shows the first two sections of a JAVADUMP. Each line of the Javadump starts with a tag that can be up to 15 characters long. You can use this metadata to parse and perform simple analysis of the contents of a Javadump.
Example 8-3 JAVADUMP title and operating environment sections
NULL ------------------------------------------------------------------------
0SECTION TITLE subcomponent dump routine
NULL ===============================
1TISIGINFO signal 11 received
1TIDATETIME Date: 2005/03/30 at 07:49:05
1TIFILENAME Javacore filename: /tmp/JAVADUMP.20050330.074905.16778293.txt
NULL ------------------------------------------------------------------------
0SECTION XHPI subcomponent dump routine
NULL ==============================
1XHSIGRECV SIGSEGV received at fc1363d8 in (unknown Module)
1XHTIME Wed Mar 30 07:49:05 2005
1XHFULLVERSION JNI J2RE 1.4.2 IBM z/OS Persistent Reusable VM build cm142-20040917
NULL
1XHOPENV Operating Environment
NULL ---------------------
2XHHOSTNAME Host : mlp1:10.0.32.42
2XHOSLEVEL OS Level : z/OS V01 R05.00 Machine 2084 Node MLP1
2XHCPUS Processors -
3XHCPUARCH Architecture : (not implemented)
3XHNUMCPUS How Many : (not implemented)
3XHCPUSENABLED Enabled : 4
NULL
You can find the environment variables for the JVM by searching for the tag 2XHENVVARS in the JAVADUMP, which shows the options, such as CLASSPATH, CICS_DIRECTORY, and JVMPROPS, that are set in the JVM profile.
The section “Current Thread Details” contains information that helps you identify the failing CICS task and program at the time of the failure. Search for the tag 1XHTHDDETAILS to find this section. The CICS program name, task number, and transaction identifier of the failing task are on the line with the tag 2XHCURRENTTHD, as shown in see Example 8-4.
Example 8-4 Current thread information from JAVADUMP
2XHCURRENTTHD "DFJIIRP.TASK14008.CIRP" (sys_thread_t:47b59290)
You find stack traces throughout the JAVADUMP by searching for the tag 3XHNATIVESTACK. Each visible stack frame contains the name and library of the function that is involved (this information is not always complete). The failing function is immediately before the Language Environment error handling routine CEEHRNUH in the stack.
Example 8-5 on page 202 shows the stack from the CEEPIPI call to invoke the JVM to the failure and Language Environment error handling. In this example, the failing function is buildPinnedFreeList in gc_free.c.
Example 8-5 Native stack in JAVADUMP
CEEHDSP CEEHDSP
CEEHRNUH CEEHRNUH
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_free.c
buildPinnedFreeList 1406
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_mwmain.c
gc0_locked 4353
/u/sovbld/cm142/cm142-20040917/src/jvm/pfm/st/msc/gc_md.c
gc_locked 74
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_mwmain.c
gc0 5073
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_mwmain.c
gcMiddlewareHeap 2000
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_main.c
gc 699
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/ci/jvm.c
JVM_GC 2117
/u/sovbld/cm142/cm142-20040917/src/java/sov/Runtime.c
Java_java_lang_Runtime_gc 74
/u/sovbld/cm142/cm142-20040917/obj/mvs390_oe_2/jvm/sov/xe/c_mmi/custom_invokers.c
mmipInvoke_V_V 816
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/xe/c_mmi/mmi_invoke_cmmi.c
mmipInvokeLazyJniMethod 650
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/xe/c_mmi/mmi_execute.c
mmipExecuteJava 2478
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/xe/common/run.c
xeRunJniMethod 1085
/u/sovbld/cm142/cm142-20040917/src/jvm/sov/ci/jni.c
jni_CallStaticVoidMethod 507
sjcscall
dfhsjcsl
@@FECB
CEEVROND
CEEPIPI CEEPIPI
CEEDUMP
The CEEDUMP is produced after any SYSDUMP processing but before a JAVADUMP is produced. A CEEDUMP is a formatted summary system dump that shows stack traces for each thread that is in the JVM process together with register information and a short dump of storage that pertains to each register. The CEEDUMP is written to the CESE transient data queue.
Use the traceback information in the CEEDUMP to find the source of the problem. The entry immediately before the entry for CEEHDSP shows the problem program. CEEHDSP is the Language Environment module that is responsible for scheduling the CEEDUMP. Example 8-6 shows traceback data from a CEEDUMP.
Example 8-6 CEEDUMP traceback
TRACEBACK:
DSA ADDR PROGRAM UNIT PU ADDR PU OFFSET ENTRY E ADDR E OFFSET STATEMENT LOAD MOD SERVICE STATUS
2E63E178 /u/sovbld/hm131s/hm131s-20020723/src/hpi/pfm/threads_utils.c
2EB098A0 +000006AA ThreadUtils_CoreDump
2EB098A0 +000006AA 1662 *PATHNAM h020723 CALL
2E63E068 /u/sovbld/hm131s/hm131s-20020723/src/hpi/pfm/interrupt_md.c
2EAEC108 +000004B0 userSignalHandler
2EAEC108 +000004B0 376 *PATHNAM h020723 CALL
2E63DFB8 /u/sovbld/hm131s/hm131s-20020723/src/hpi/pfm/interrupt_md.c
2EAEC670 +000000B6 intrDispatch 2EAEC670 +000000B6 642 *PATHNAM h020723 CALL
2E63DF00 2DED9938 +0000001A @@GETFN 2DED9890 +000000C2 CEEEV003 CALL
2E63DE80 CEEVASTK 2DCCC420 +00000126 CEEVASTK 2DCCC420 +00000126 CEEPLPKA CALL
2E32BCC0 2DFF2B80 +00000736 __zerros 2DFF2B80 +00000736 CEEEV003 DRIVER9 CALL
2E329128 CEEHDSP 2DC16848 +00000C0C CEEHDSP 2DC16848 +00000C0C CEEPLPKA CALL
2E3286A8 /u/sovbld/hm131s/hm131s-20020723/src/zip/sov/ZipEntry.c
31F6EB38 +00000252 Java_java_util_zip_ZipEntry_initFields
31F6EB38 +00000252 99 *PATHNAM h020723 EXCEPTION
2E3285C8 java/util/zip/ZipEntry.java
32CEE95C +000000E4 java/util/zip/ZipEntry.initFields(J)V
32CEE95C +000000E4 0 CALL
You can change the level of information that the Language Environment produces when a JVM crash occurs by overriding the TRAP and TERMTHDACT runtime options in DFHJVMRO. We recommend that you do not override these values unless IBM advises you to. The default values that CICS set for the enclave in which the JVM runs are TERMTHDACT(DUMP,,96) and TRAP(ON,NOSPIE).
SYSDUMP
A sysdump is captured using the MVS IEATDUMP service, which produces a data set that contains an unformatted transaction dump. You use MVS Interactive Problem Control System (IPCS) to format the dump.
The default name for the data set that is produced is &userid.SYSTDUMP.&date.T&time. You can use the environment variable JAVA_DUMP_TDUMP_PATTERN to set your own name.
Messages appear in stderr when the JVM requests a sysdump. Example 8-7 shows the messages that we saw. You can see that we use JAVA_DUMP_TDUMP_PATTERN to set our own name for the dump data set.
Example 8-7 Messages in stderr when a dump is captured
JVMDG217: Dump Handler is Processing Signal 4 - Please Wait.
JVMHP002: JVM requesting System Transaction Dump
JVMHP012: System Transaction Dump written to PLOWMAN.JVM.TDUMP.COMKZCES.D050419.T231519
JVMDG303: JVM Requesting Java core file
JVMDG304: Java core file written to /u/plowman/cics630/workdir/JAVADUMP.20050419.231606.83886118.txt
JVMDG215: Dump Handler has Processed Exception Signal 4.
You use IPCS to format the dump. VERBX LEDATA ‘CEEDUMP’ formats the Language Environment traceback information. You can also use the appropriate CICS formatting exit to format CICS data, such as the internal trace table. CICS Operations & Utilities Guide, SC34-6431, tells you how to use IPCS to format CICS dumps.
8.3.2 Heapdump
Heapdump is a dump file that the JVM generates of all the live objects on the Java heap that running applications are using. The heapdump is stored in a Portable Heap Dump (phd) file, which is a compressed binary file. You can use various tools to analyze the heapdump to know what is on the heap, what is using the most memory, and why the garbage collection cannot recycle it.
By default, JVM automatically generates heapdump when the heap is exhausted. You can also change this behavior by using the -Xdump:heap parameter in the JVM profile.
There are tools that can help you to understand the non-readable output heapdump. The preferred heapdump analysis tool is Memory Dump Diagnostic for Java (MDD4J). Figure 8-1 shows how to use MDD4J to analyze the heapdump. You can find it in IBM Support Assistant V4.0 Tools, at the following Web site:
Figure 8-1 Using MDD4J to analyze the heapdump
There are also other utilities that can help you to analyze the heapdump. You can find more information at:
Of course you still have alternatives. You can also get a classic text-formatted heapdump by specifying the -Xdump:heap:opts=CLASSIC parameter in the JVM profile, which gives you a human-readable view of the heap. For more information about how to understand the classic heapdump, refer to SDK DIagnostics Guide, SC34-6650.
8.3.3 Monitoring garbage collection cycles
The JVM intermittently performs garbage collection. Although Java does not specify exactly when garbage collection occurs, there are circumstances that make garbage collection likely. If the heap free space drops below a given threshold, a garbage collection is likely. Typically if this cycle fails to free sufficient heap storage, the JVM might request more heap storage from z/OS (up to the maximum heap size). If the program invokes System.gc(), this can cause the JVM to run a garbage collection cycle at some point, but this is not guaranteed. The JVM also might run garbage collection at regular (or not so regular) intervals.
Because garbage collection stops all processing and can take a significant period of time to complete, it can cause performance problems.
There are times that the garbage collection can result in problems for your application. Sometimes the garbage collection occurs too often, which brings a hugh overhead. Sometimes it brings too much pause time. And sometimes it just does not work as expected, and you still get an OutOfMemoryError exception. In such cases, you might want to see what is happening inside JVM.
The first tool to use to diagnose the garbage collection problems is the verbose logging. You can enable it by specifying the -verbose:gc parameter in the JVM profile. The output is written to syserr by default. Example 8-8 is a sample of the output when a global collection is performed.
Example 8-8 Sample -verbose:gc output during the global garbage collection
<gc type="global" id="5" totalid="5" intervalms="18.880">
<compaction movecount="9282" movebytes="508064" reason="forced compaction" />
<expansion type="tenured" amount="1048576" newsize="3145728" timetaken="0.011" reason="insufficient free space following gc" />
<refs_cleared soft="0" weak="0" phantom="0" />
<finalization objectsqueued="0" />
<timesms mark="7.544" sweep="0.088" compact="9.992" total="17.737" />
<tenured freebytes="1567256" totalbytes="3145728" percent="49" >
<soa freebytes="1441816" totalbytes="3020288" percent="47" />
<loa freebytes="125440" totalbytes="125440" percent="100" />
</tenured>
</gc>
 
You can use the tool The IBM Monitoring and Diagnostic Tools for Java - Garbage Collection and Memory Visualizer, Figure 8-2 on page 206, to get a nice graph about heap usage and garbage collection results by using the output of -verbose:gc as the input file. It is also included in the IBM Support Assistant V4.0 Tools, which are found at:
Figure 8-2 The IBM Monitoring and Diagnostic Tools for Java - Garbage Collection and Memory Visualizer
You can also get more detailed information by enabling one or more trace garbage collectors (TGC) by specifying the -Xtgc parameter in the JVM profile. For more information, refer to SDK DIagnostics Guide, SC34-6650.
8.3.4 JVM stdout and stderr
The JVM and the applications that it is running might write data to stdout and stderr. The JVM writes informational and error messages to stdout and stderr, for example, if the JVM abends, messages are written to stderr. The application itself might write messages to stdout and stderr, which might provide important clues in resolving a problem.
The location of these files is specified in the JVM profile using the options STDOUT and STDERR. Look in the JVM profile to find where stdout and stderr are written.
The default names for stdout and stderr are dfhjvmout and dfhjvmerr, respectively. By default they are created in the WORK_DIR directory. You can use your own file name or specify a full path name. Remember, you can also use the symbol &APPLID; in the JVM profile to substitute the CICS region applid in any name at runtime.
You can further modify the name of the stdout and stderr files by using the -generate option in the JVM profile (for example, STDOUT=dfhjvmerr -generate. There must be a space before the -generate), which tells CICS to generate a specific file for the JVM by appending the following information to the specified file name:
region The applid of the CICS region
time The current time in the form yydddhhmmss
.txt A literal string suffix to indicate that the file contains readable data
An example of a generated name is dfhjvmout.SCSCPJA7.05101150145.txt.
We do not recommend that you use the -generate option in a production environment because it can affect JVM performance. However, you might want to use it in a test environment to keep output from different test cases separate.
 
Note: The USEROUTPUTCLASS option in the JVM profile specifies the name of a class that is used to redirect output from the JVM. If this option is set in the JVM profile, you must know how the specified class deals with output from the JVM. Java Applications in CICS, SC34-6238, contains more information about redirecting JVM output using these classes.
8.3.5 JVM method tracing
Using the powerful tool method trace, you can trace method entry and exit in any Java code. You do not add any hooks or calls to existing code. 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.
You control method trace by specifying system properties, which you specify in the JVM profile. All of the method trace properties are of the format ibm.dg.trc.<something>. The set of these properties is quite large and is fully described in SDK DIagnostics Guide, SC34-6650.
If you want method trace to format, set two properties:
ibm.dg.trc.print: Set this property to ’mt’ to invoke method trace.
ibm.dg.trc.methods: Set this property to decide what to trace.
Use the methods parameter to control what is traced. To trace everything, set it to methods=*.*, which we do not recommend d because you are certain to get overwhelmed by the amount of output. The methods parameter is formally defined as:
ibm.dg.trc.methods=[[!]method_spec[,...]]
Where method_spec is formally defined as:
{*|[*]classname[*]}.{*|[*]methodname[*]}[()]
The delimiter between the parts of the package name is a forward slash (/). The exclamation point (!) in the methods parameter is not an operator that allows you to tell the JVM not to trace the specified method or methods. The parentheses () that are in the method_spec define whether to trace method parameters.
The formatted trace output is written to stderr.
We traced the method calls in the HelloCICSWorld sample program by setting the properties ibm.dg.trc.print=mt and ibm.dg.trc.methods=examples/HelloWorld/HelloCICSWorld.*(). Example 8-9 on page 208 shows the information written to stderr. Message JVMDG200 shows the diagnostics properties set. The HelloCICSWorld class only has a main method, so the output shows entry and exit to main.
Example 8-9 Formatted method trace in stderr
JVMDG200: Diagnostics system property ibm.dg.trc.print=mt
JVMDG200: Diagnostics system property ibm.dg.trc.methods=examples/HelloWorld/HelloCICSWorld.*()
JVMDG200: Diagnostics system property ibm.jvm.events.output=event.log
10:11:59.353*0x349A8280 40011 > examples/HelloWorld/HelloCICSWorld.main Bytecode static method, Signature: (Lcom/ibm/cics/server/CommAreaHolder;)
10:11:59.355 0x349A8280 40022 < examples/HelloWorld/HelloCICSWorld.main Bytecode static method
Writing trace data to stderr in real time is fine for low volume and non-performance-critical instances. For larger volumes and performance-critical tracing, you must not write formatted output to stderr. You can direct unformatted trace output to in-storage buffers or to one or more external files using buffered I/O.
Writing trace to buffers
The use of in-storage buffers for trace is an efficient method of running trace because no explicit I/O is performed until either a problem is detected or an API is used to snap the buffers to a file. To examine the trace data, you must snap or dump, and then format the buffers. Buffers are snapped when:
An uncaught Java exception occurs.
An operating system signal or exception occurs.
The com.ibm.jvm.Trace.snap() Java API is called.
The JVMRI TraceSnap function is called.
The resulting snap file is placed in the current working directory with a name in 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.
Use the ibm.dg.trc.buffers system property to specify the size of the buffers that are allocated for each thread that makes trace entries. See SDK DIagnostics Guide, SC34-6650 for more information.
Writing trace to an external file
You can write trace data to a file continuously as an extension to the in-storage trace, but, instead of one buffer per thread, at least two buffers per thread are allocated, which allows the thread to continue to run while a full trace buffer is written to disk. Depending on trace volume, buffer size, and the bandwidth of the output device, multiple buffers might be allocated to a given thread to keep pace with trace data that is generated.
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 ibm.dg.trc.buffers system property. For long-running trace runs, a wrap option is available to limit the file to a given size. See the ibm.dg.trc.output property in SDK DIagnostics Guide, SC34-6650, for details. You must use the trace formatter to format trace data from the file.
You can use the -Dibm.dg.trc.external=mt option in the properties file to send the method trace to the CICS auxiliary trace facility.
 
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.
Formatting trace
The trace formatter is a Java program that runs on any platform and can format a trace file from any platform. The formatter, which is shipped with the SDK in core.jar, also requires a file called TraceFormat.dat, which contains the formatting templates. This file is shipped in jre/lib.
You invoke the trace formatter by typing:
java com.ibm.jvm.format.TraceFormat input_filespec [output_filespec] [options]
Where com.ibm.jvm.format.TraceFormat is the traceformatter class, input_filespec is the name of the binary trace file to be formatted, and output_filespec is the optional output file name. If it is not specified, the default output file name is input_filespec.fmt.
CICS SJ domain tracing for JVMs
In addition to the trace points that the JVMs produce, CICS provides some standard trace points in the SJ (JVM) domain to trace the actions that CICS takes in setting up and managing JVMs and the shared class cache. These are available at CICS trace levels 0, 1 and 2.
You can activate the SJ domain trace points at levels 0, 1, and 2 using the CETR Component Trace screens. Select tracing by component, in the CICS Problem Determination Guide, to learn how to do this.
The SJ domain includes a level 2 trace point SJ 0224, which shows you a history of the programs that used each JVM.
“JVM domain trace points”, in the CICS Trace Entries manual, has details of all of the standard trace points in the SJ domain.
8.3.6 JVM class loader tracing
The z/OS Persistent Reusable JVM that CICS uses has three classpaths on which classes can be included:
Trusted middleware class path
Shareable application class path
Standard class path
There is a class loader for each of these class paths. The status of a class within the JVM is dictated by its class loader. If a class is loaded by the wrong class loader, the behavior of the application can change, for example, a JVM can become unresettable.
There can be a large number of class and jar files on the classpaths, and you might not be able to easily identify on which classpath a class is included. Using JVM class loader tracing you can obtain which class loader is responsible for loading a class.
You enable class loader tracing by specifying the system property ibm.verbose.cl in the properties file for the JVM. The output is written to stdout.
You can trace loading for just one class or for many classes. You can use wildcard characters in the class name, for example:
ibm.cl.verbose=examples.HelloWorld.HelloCICSWorld
ibm.cl.verbose=examples.HelloWorld.HelloCICSWorld,com.ibm.cics.server.Task
ibm.cl.verbose=com.ibm.cics.server.T*
 
Fully-qualified class name: The fully qualified class name must be specified.
We trace the loading of the sample CICS class HelloCICSWorld by adding ibm.cl.verbose=examples.HelloWorld.HelloCICSWorld to the systems properties file for the JVM. Example 8-10 shows the output. The output shows that HelloCICSWorld is loaded by the standard Java class loader. You can also obtain in which jar file or directory the class was found.
Example 8-10 JVM class loader trace output
ExtClassLoader attempting to find examples.HelloWorld.HelloCICSWorld
ExtClassLoader using classpath /usr/lpp/java142s/J1.4/lib/ext/dumpfmt.jar:/usr/lpp/java142s/J1.4/lib/ext/gskikm.jar:/usr/lpp/java14r
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/dumpfmt.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/gskikm.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjcefips.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjceprovider.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjce4758.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjsseprovider2.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmpkcs11impl.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/indicim.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/jaccess.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ldapsec.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/oldcertpath.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/recordio.jar
ExtClassLoader could not find examples.HelloWorld.HelloCICSWorld
 
MiddlewareClassLoader attempting to find examples.HelloWorld.HelloCICSWorld
MiddlewareClassLoader using classpath /SYSTEM/cicsts/cics630/lib/dfjcicsras.jar:/SYSTEM/cicsts/cics630/lib/ras.jar:/SYSTEM/cicsts/cr
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcicsras.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/ras.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjwrap.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjorb.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcont.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcsi.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcics.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcdmn.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjjts.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjadjr.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/omgcos.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjname.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/websphere.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcci.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/ctg/ctgclient.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/ctg/ctgserver.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/ctg/ccf.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjejbdd.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/standard/ejb/2_0/ejb20.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/standard/jta/1_0_1/jta-specr
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/standard/jca/connector.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/db2710/db2710/jcc/classes/db2jcc.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/db2710/db2710/jcc/classes/db2jcc_javax.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/db2710/db2710/jcc/classes/db2jcc_license_r
MiddlewareClassLoader could not find examples.HelloWorld.HelloCICSWorld
 
AppClassLoader attempting to find examples.HelloWorld.HelloCICSWorld
AppClassLoader using classpath /u/plowman/cics630/myprogs/myCICSPrograms.jar:/u/plowman/cics630/samples/dfjcics:/u/plowman/cics630/s
AppClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /u/plowman/cics630/myprogs/myCICSPrograms.jar
AppClassLoader found examples/HelloWorld/HelloCICSWorld.class in /u/plowman/cics630/samples/dfjcics
AppClassLoader found examples.HelloWorld.HelloCICSWorld
8.3.7 Shared classes diagnostics
Class sharing in the IBM Version 5.0 SDK offers a transparent and dynamic means of sharing all loaded classes, both application classes and system classes, and placing no restrictions on JVMs that are sharing the class data (unless runtime bytecode modification is used).
Sharing all immutable class data for an application between multiple JVMs has obvious benefits:
The virtual memory footprint reduction when using more than one JVM instance can be significant.
Loading classes from a populated cache is faster than loading classes from disk because the classes are already in memory and are already partially verified. Therefore, class sharing also benefits applications that regularly start new JVM instances doing similar tasks. The cost to populate an empty cache with a single JVM is minimal, and when more than one JVM is populating the cache concurrently, this activity is typically faster than both JVMs loading the classes from disk.
When you are running in shared classes mode, a number of diagnostics tools can help you. The verbose options are used at runtime to show cache activity. You can use the printStats and printAllStats utilities to analyze the contents of a shared class cache.
Verbose output
The verbose suboption of -Xshareclasses gives the most concise and simple diagnostic output on cache usage. Verbose output typically looks like Example 8-11.
Example 8-11 Sample output of -Xshareclasses:name=myCache,verbose
java -Xshareclasses:name=myCache,verbose -Xscmx10k HelloWorld
[-Xshareclasses verbose output enabled]
JVMSHRC158I Successfully created shared class cache "myCache"
JVMSHRC166I Attached to cache "myCache", size=10200 bytes
JVMSHRC096I WARNING: Shared Cache "myCache" is full. Use -Xscmx to set cache size. Hello
JVMSHRC168I Total shared class bytes read=0. Total bytes stored=9284
 
The output in Example 8-11 shows that a new cache, called myCache, was created, which was only 10 kilobytes in size, and the cache filled up almost immediately. The message displayed on shutdown shows how many bytes were read or stored in the cache.
VerboseIO output
The verboseIO output is far more detailed and is used at runtime to show classes that are stored and found in the cache. You enable verboseIO output by using the verboseIO suboption of -Xshareclasses.
VerboseIO output provides information about the I/O activity occurring with the cache, with basic information about find and store calls. With a cold cache, you see trace like Example 8-12.
Example 8-12 Trace
Finding class org/eclipse/ui/internal/UIWorkspaceLock in shared cache for cldr id 0... Failed.
Finding class org/eclipse/ui/internal/UIWorkspaceLock in shared cache for cldr id 3... Failed.
Finding class org/eclipse/ui/internal/UIWorkspaceLock in shared cache for cldr id 17... Failed.
Storing class org/eclipse/ui/internal/UIWorkspaceLock in shared cache for cldr id 17... Succeeded.
Each classloader is given a unique ID, and the boostrap loader is always 0. In the trace in Example 8-12 on page 211, you see classloader 17 obeying the classloader hierarchy of asking its parents for the class. So each of its parents consequently asks the shared cache for the class. Because it does not yet exist in the cache, all the find calls fail and classloader 17 stores it.
After the class is stored, you see the output in Example 8-13.
Example 8-13 Trace output after the class is stored
Finding class org/eclipse/ui/internal/UIWorkspaceLock in shared cache for cldr id 0... Failed.
Finding class org/eclipse/ui/internal/UIWorkspaceLock in shared cache for cldr id 3... Failed.
Finding class org/eclipse/ui/internal/UIWorkspaceLock in shared cache for cldr id 17...Succeeded.
Again, the classloader obeys the hierarchy, with its parents asking the cache for the class first. It succeeds for the correct classloader.
Verbose Helper, printStats utility, and printAllStats utility
There are other utilities that can give you more information about the class cache. You can enable them by using the following parameter in the JVM profile.
-Xshareclasses:verboseHelper
-Xshareclasses:printStats,name=<cache_name>
-Xshareclasses:printAllStats,name=<cache_name>
More more information about the shared classes diagnose utilities is available in SDK DIagnostics Guide, SC34-6650.
8.4 Interactive debugging
In this section, we discuss several techniques that can perform an interactive debugging of the Java program running in CICS.
8.4.1 Execution diagnostic facility
You can use the execution diagnostic facility (EDF) to test an application program online without modifying the program or the program-preparation procedure. The CICS execution diagnostic facility is supported by the CICS-supplied transaction, CEDF.
 
Invoking CEDF: You can also invoke CEDF indirectly through another CICS-supplied transaction, CEDX, which enables you to specify the name of the transaction you want to debug. When this section refers to the CEDF transaction (for example, when it explains about CICS starting a new CEDF task) remember that the CEDX command might have invoked it.
EDF intercepts the execution of CICS commands in the application program at various points, which allows you to see what is happening. Each command is displayed before execution, and most are displayed after execution is complete. Screens that the application program sends are preserved, so you can converse with the application program during testing, just as a user does on a production system.
CICS Application Programming Guide, SC34-6231 has more information about EDF and user instructions for EDF.
When used with a JCICS program, CEDF intercepts the CICS commands that the Java Native Interface (JNI) programs invoke, which provide the interface between JCICS classes and CICS. There might not be an obvious relationship between the JCICS class method and the CICS command, for example, the HelloCICSWorld sample uses the Task.out.println method to send a message to the user terminal. The JNI program invokes the SEND command to write to the panel. Example 8-14 shows the line of Java source code to write to the panel (t is an instance of Task) and the image from CEDF showing the intercepted SEND command.
Example 8-14 Writing to the panel using Task.out.println method
Task.getTask().out.println("Hello from a Java CICS application");
 
TRANSACTION: JHE2 PROGRAM: DFJ$JHE2 TASK: 0006530 APPLID: SCSCPJA7 DISPLAY: 00
STATUS: ABOUT TO EXECUTE COMMAND
EXEC CICS SEND
FROM ('.A&Hello from a Java CICS application..')
LENGTH (39)
NOHANDLE
8.4.2 Debugging using Rational Developer for System z
The JVM in CICS supports the Java Platform Debugger Architecture (JPDA), which is the standard debugging mechanism that is provided in the Java 2 Platform. This architecture provides a set of APIs that allow the attachment of a remote debugger to a JVM. A number of third-party debug tools, including Rational Developer for System z, are available to exploit JPDA and can be used to attach to and debug a JVM that is running a Java program. Typically, the debug tool provides a graphical user interface that runs on a workstation and allows you to follow the application flow, set breakpoints and step through the application source code, and examine the values of variables.
When you start the JVM in debug mode, the JVMDI interface is activated and additional threads are started in the JVM. One of these threads handles communication with the remote debugger. The other threads monitor the application that is running in the JVM. You can issue commands in the remote debugger, for example, to set break points or to examine the values of variables in the application. These commands are activated by the listener and event handler threads in the JVM.
We use the debugger that is provided in Rational Developer for System z to show how to attach a debugger to a CICS JVM. We chose the HelloWorld sample program HelloCICSWorld in the getting started chapter as the application to be debugged.
JVM profile changes
To run a JVM in debug mode and allow a JPDA remote debugger to be attached, you must set some options in the JVM profile for the JVM:
-Xdebug=YES
This is needed to start the JVM in debug mode (that is, with the JPDA interfaces active).
-Xrunjdwp=(suboption=...,suboption=...)
This option specifies the details of the connection between the debugger and the CICS JVM. These details include the TCP/IP address to be used for the connection and the sequence in which the connection occurs. Different debuggers have different connection requirements and capabilities. Refer to the documentation that is provided with the debugger.
We specify the following suboptions for the connection between IBM Rational Software Development Platform and the CICS JVM:
Xrunjdwp=(transport=dt_socket,server=y,address=8000)
This set of suboptions specifies that:
 – The standard TCP/IP socket connection mechanism is used.
 – The JVM starts first (server=y) and waits for the debugger to attach to it.
 – The CICS JVM listens on TCP/IP port 9876 for a debugger to attach to it.
REUSE=NO
A JVM that was run in debug mode is not a candidate for reuse. Set this option to NO to ensure that the JVM is discarded after the debug session.
When you set these options in a JVM profile, any CICS JVM program that uses that profile runs in debug mode (and waits for attach from, or attempts to attach to a debugger). You must therefore ensure that the JVM profile applies only to programs that you want to debug.
Instead of configuring any of the CICS-supplied sample profiles for debug, you must create a separate JVM profile specifically for debug use, and set the appropriate CICS PROGRAM resource definition or use the CADP transaction to use this debug JVM profile.
We recommend that you copy the existing JVM profile to a new file and add the options to enable remote debugging. Use CADP to enable the transaction to be debugged by switching to the debug profile, which ensures that the JVM options (which influences the behavior of the Java application) are identical.
 
Rational Developer for System z configuration
We use the debugger in Rational Developer for System z. The source code for the application you want to debug must be loaded into the Rational Developer for System z. We use the Java project that we created in Chapter 5., “Writing Java 5 applications for CICS” on page 75.
 
Adding dfjcics.jar: You must add dfjcics.jar to the Java build path for your project because this application uses JCICS.
Figure 8-3 on page 215 shows the Java perspective within Rational Developer for System z displaying the JCICS HelloWorld project:
The package explorer pane on the left shows the project, package, and class hierarchy. It also shows dfjcics.jar on the build path.
The center pane shows the source code of HelloWorld. We set a breakpoint at line 15 of the source, which is indicated by the blue button to the left of the pane.
Hovering over the button displays the text shown.
Double clicking in the left edge of the pane toggles a line breakpoint on and off.
Figure 8-3 Sample HelloWorld project
You must create a Remote Java Application configuration within the Debug Perspective that specifies:
The IP address (or host name) of the z/OS system that hosts the CICS region.
The TCP/IP port number that the CICS JVM is using. (This is the same number that is specified to CICS on the Xrunjdwp option in the JVM profile.)
That a standard TCP/IP socket connection (Socket Attach) is to be used.
To open the Debug configuration window:
1. Click the arrow to the right of the icon in the toolbar.
2. Click the icon in the menu. Figure 8-4 on page 216 is displayed.
Figure 8-4 Configuring remote Java application
Debugging the application
You are now ready to start the interactive debugging session:
1. Enter the transaction identifier on CICS to run the Java program to be debugged. For our example, we enter HELO, which starts the JVM in debug mode. Your terminal session will hang. The JVM is waiting for the connection from the remote debugger.
2. Start the debug configuration previously created in the Rational Developer for System z. The debugger connects to the JVM in CICS, the debug perspective opens, and you can start debugging. Figure 8-5 on page 217 shows the debug perspective.
3. From the debug perspective you can step through the code of your class, inspect and change variables, and set new breakpoints. If the source code is available, you can also interactively debug other classes that were invoked during the execution of your application program.
Figure 8-5 Debug perspective in Rational Developer for System z
 
Syncing the byte code and source code: Be careful to keep the byte code and the source code in sync, that is, make sure that you re-export the byte code to the host after you change the source code on the development workstation.
8.4.3 CICS Application Debugging Profile
Using the CICS Application Debugging Profile (CADP) CICS-supplied transaction you can manage application debugging profiles for both traditional and Java programs.
The benefit of using CADP is that you can dynamically switch the JVM profile at invocation time based on certain runtime characteristics. As we mentioned in previous section, if you want to debug a Java program in CICS, you need a special JVMProfile that specifies both REUSE=NO and -Xdebug=YES and the JDWP options, such as -Xrunjdwp:transport=dt_socket,address=workstationHostname:debuggingPortNumber. Each developer typically needs their own variant of this debugging profile.
Look at this example: If you want to debug a particular Java program, you can tell CADP that whenever user ID 'FRED' runs Java program 'com.ibm.cics.example.MyExample', CICS dynamically switches the JVMProfile from the normal one (typically DFHJVMPR) to a custom one, such as FREDDEBG, which has Fred's personal debugging parameters. Other users can set up similar profiles in the same CICS region.
At runtime, CICS spots that MyExample is to be linked if the current USERID is FRED. The debugging JVM profile is used rather than DFHJVMPR, which in turn results in the JVM attaching to the debugger that is running on the workstation. It is a flexible solution that works nicely with multiple users. It also integrates reasonably well with the CADP-based debugging for other languages, such as COBOL and PL/I. Figure 8-6 shows the CICS Application Debugging Profile Manager.
CADP also has a Web-based interface in CICS so that the developer can set up the CADP debugging profiles without ever using a 3270 terminal. For more information, check the CADP chapter in the CICS manual, CICS Supplied Transactions, SC34-6817.
Figure 8-6 CICS Application Debugging Profile Manager
8.4.4 The CICS JVM plug-in mechanism
In addition to the standard JPDA debug interfaces in the JVM, CICS provides a set of interception points (or plug-ins) in the CICS Java middleware, which can be of value to developers for debugging applications. These interception points allow additional Java programs to be inserted immediately before and after the application Java code is run. Information about the application (for example, classname and method name) is made available to the plug-in programs. The plug-in programs can also use the JCICS API to obtain information about the application. You can use these interception points in conjunction with the standard JPDA interfaces to provide additional CICS-specific debug facilities. You can also use them for purposes other than debugging, in a similar way to user exit points in CICS.
The programming interface consists of two Java interfaces:
DebugControl Defines the method calls that can be made to a user-supplied implementation
Plugin Provides a general purpose interface for registering the plug-in implementation
These interfaces are supplied in dfjwrap.jar and documented in JAVADOC HTML.
These plug-ins are not described further in this book. Refer to Java Applications in CICS, SC34-6238, for more information.
 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset