Hints and Tips for Java on z/OS

(last updated August, 2011)

There are five areas of information.

For additional IBM value add content.

We welcome additional tips. Send comments to us through the contact us link. Please specify performance or hints and tips in the comment on: section.


Considerations

When using the product


Java and LE runtime options

These are described in the LE Programming Reference (PDF, 5.24MB). The java executables (java, javac, javah, JZOS Batch Launcher, etc.) are built with a recommended set of runtime options.

You can use the runtime option RPTOPTS(ON) to produce a report that display the options in effect for the java SDK executable.


JCL REGION size parameter

This needs to be large enough to allow for all of the heap and stack storage requirements, plus LE and Java code, and LE internal control blocks. OutOfMemoryError is not very granular. You may be able to get further useful information by inspecting the Java stack traceback.


Java Start Up Time

When running hundreds or thousands of small Java batch jobs, the Java start up elapsed time and CPU time become an important performance measurement for many customers. Use of the following Java options makes it possible to reduce the Java startup times for applications that start a new JVM frequently:

Java Shared Classes and AOT Examples

You can see below that in this example, the default shared class library size of 16 megabytes was too large for the current BPXPRMxxx setting, which has resulted in an error message. This problem was caused by BPXPRMxx IPCSHMMPAGES set to 8 MegaBytes, which was less than the defalut shared class library size.

$ java -Xshareclasses:listAllCaches
JVMSHRC005I No shared class caches available
Could not create the Java virtual machine.

In this next java command, the -Xscmx1m option was specified to use a shared class size of 1 Megabytes. This command was successful. Note that this example requires access to a HelloWorld java program.

> java -Xscmx1m -Xshareclasses:name=cache1 HelloWorld
Hello World

The following commands demonstrate how to use different shared classes with different sizes.

> java -Xshareclasses:listAllCaches
Shared Cache       OS shmid      in use      Last detach time
cache1             1646599       0           Fri Jun 10 10:43:47 2009

Could not create the Java virtual machine.

> java -Xscmx8m -Xshareclasses:name=cache2 HelloWorld
Hello World

> java -Xscmx8m -Xshareclasses:name=cache3 HelloWorld
Hello World

Using the ipcs -bom command, the 1 megabyte shared memory segment is displayed for user TESTER

> ipcs -bom

IPC status as of Fri Nov 14 10:52:15 2008
Shared Memory:
T             ID     KEY          MODE       OWNER    GROUP   NATTCH   SEGSZPG PGSZ     SEGSZ
m         8196 0x012ed3f0 --rw-------       TCP   DEPTD60          1               1     4K         4096
m         8197 0x022ed3f0 --rw-------       TCP   DEPTD60          1               1     4K         4096
m         8198 0x032ed3f0 --rw-------       TCP   DEPTD60          1               1     4K         4096
m      1646599 0x0100f6f5 --rw-------    TESTER   DEPTD60          0             256     4K      1048576
m         8200 0x0100b3f5 --rw-------    TESTER   DEPTD60          0            2048     4K      8388608
m         8201 0x0100bcf5 --rw-------    TESTER   DEPTD60          0            2048     4K      8388608

The following java commands demonstrates options to display shared class information.

$ java -Xshareclasses:listAllCaches
Shared Cache       OS shmid      in use      Last detach time
cache1             1646599       0           Fri Nov 14 10:50:33 2008

cache2             8200          0           Fri Nov 14 10:51:57 2008

cache3             8201          0           Fri Nov 14 10:52:12 2008
Could not create the Java virtual machine.

> java -Xshareclasses:name=cache1,printStats

Current statistics for cache "cache1":

base address       = 0x26F00058
end address        = 0x26FFFFF8
allocation pointer = 0x26FFD418

cache size         = 1048488
free bytes         = 604
ROMClass bytes     = 1037248
Metadata bytes     = 10636
Metadata % used    = 1%

# ROMClasses       = 234
# Classpaths       = 1
# URLs             = 0
# Tokens           = 0
# Stale classes    = 0
% Stale classes    = 0%

Cache is 99% full

Could not create the Java virtual machine.

> java -Xshareclasses:name=cache2,printStats

Current statistics for cache "cache2":


base address       = 0x26F00058
end address        = 0x276FFFF8
allocation pointer = 0x2703F508

cache size         = 8388520
free bytes         = 7067020
ROMClass bytes     = 1307824
Metadata bytes     = 13676
Metadata % used    = 1%

# ROMClasses       = 306
# Classpaths       = 2
# URLs             = 0
# Tokens           = 0
# Stale classes    = 0
% Stale classes    = 0%

Cache is 15% full

Could not create the Java virtual machine.

The following java command demonstrates how to destroy or remove a shared class library. In this example the shared memory segment for the shared class is also removed. It should be noted that the share memory for java shared classes is not removed when the JVM terminates. The following java command with the destroy option must be issued to remove the shared class and its shared memory as shown below.

> ipcs -bom

IPC status as of Fri Nov 14 10:52:15 2008
Shared Memory:
T            ID     KEY          MODE         OWNER     GROUP   NATTCH   SEGSZPG PGSZ      SEGSZ
m         8196 0x012ed3f0 --rw-------       TCP   DEPTD60            1               1     4K           4096
m         8197 0x022ed3f0 --rw-------       TCP   DEPTD60            1               1     4K           4096
m         8198 0x032ed3f0 --rw-------       TCP   DEPTD60            1               1     4K           4096
m      1646599 0x0100f6f5 --rw-------    TESTER   DEPTD60            0             256     4K        1048576
m         8200 0x0100b3f5 --rw-------    TESTER   DEPTD60            0            2048     4K        8388608
m         8201 0x0100bcf5 --rw-------    TESTER   DEPTD60            0            2048     4K        8388608

> java -Xshareclasses:name=cache1,destroy
JVMSHRC010I Shared Cache "cache1" is destroyed
Could not create the Java virtual machine.

> ipcs -bom

IPC status as of Fri Nov 14 10:57:31 2008
Shared Memory:
T           ID     KEY          MODE        OWNER     GROUP   NATTCH   SEGSZPG PGSZ      SEGSZ
m       8196 0x012ed3f0 --rw-------       TCP   DEPTD60            1              1      4K          4096
m       8197 0x022ed3f0 --rw-------       TCP   DEPTD60            1              1      4K          4096
m       8198 0x032ed3f0 --rw-------       TCP   DEPTD60            1              1      4K          4096
m       8200 0x0100b3f5 --rw-------    TESTER   DEPTD60            0           2048      4K       8388608
m       8201 0x0100bcf5 --rw-------    TESTER   DEPTD60            0           2048      4K       8388608


64 Bit Java

Use of 64 bit Java may make it possible to define large Java heap size to avoid out of virtual memory conditions and improve application reliability. Large Java heaps also means that Garbage Collection will occur less frequently, which may improve your applications performance. Use of 64 bit Java Compress References option -Xcompressedrefs and large page option -Xlp in IBM Developer Kit for Java 6 will improve performance of 64 bit Java significantly.

Examples First Time Using 64 bit Java

To be able to run 64 bit Java, the memory limit or memlimit for memory above the bar must be sufficient to run the 64 bit application. Before attempting to use 64 bit Java for the first time on z/OS, check that the memlimit "memory above the 2 Gigabyte bar" is not zero by using the ulimit command as shown below. In this example the memory above the bar is 1000 megabytes. Your configuration may be different.

> ulimit -a
core file         8192b
cpu time          unlimited
data size         unlimited
file size         unlimited
stack size        unlimited
file descriptors  1500
address space     unlimited
memory above bar  1000m

The following 64 bit Java command is invoked to display the java version. The following command displays "s390x-64" , which means the 64 Bit Java is being run.

> java -version
java version "1.6.0"
Java(TM) SE Runtime Environment (build pmz6460sr5-20090604_01(SR5))
IBM J9 VM (build 2.4, J2RE 1.6.0 IBM J9 2.4 z/OS s390x-64
jvmmz6460sr5-20090519_35743 (JIT enabled, AOT enabled
J9VM  - 20090519_035743_BHdSMr
JIT   - r9_20090518_2017
GC    - 20090417_AA)
JCL   - 20090529_01

Next example will use -verbose:gc java command option to display the default Java heap size values. In this example maxHeapSize value is 0x20000000 or 512 megabytes.

> java -verbose:gc -version
 
<initialized>
  <attribute name="gcPolicy" value="-Xgcpolicy:optthruput" />
  <attribute name="maxHeapSize" value="0x20000000" />
  <attribute name="initialHeapSize" value="0x400000" />
  <attribute name="compressedRefs" value="false" />
  <attribute name="pageSize" value="0x1000" />
  <attribute name="requestedPageSize" value="0x1000" />
</initialized>

The next examples demonstrates changing the memlimit for above the bar storage from 1000 megabytes to 200 megabytes using the ulimit -M option. After setting 200 megabyte above the bar storage, the 64 bit java command is invoked with default heap size of 200 megabytes. As expected the java command fails. Note this example requires access to a Java HelloWorld program.

> ulimit -M 200

> ulimit -a
core file         8192b
cpu time          unlimited
data size         unlimited
file size         unlimited
stack size        unlimited
file descriptors  1500
address space     unlimited
memory above bar  200m
 
> java HelloWorld
CEE0814S Insufficient storage was available to extend the stack.
[1] + Done(139) java HelloWorld
  16908772 Segmentation violation /PRIPKC/J6.0_64/bin/java

If the the first time use of 64 bit Java fails, the first thing to check is ulimit -a memory above the bar storage is sufficient to run a java application.

The next example shows invoking java command for HelloWorld wth a smaller maximum heap size value of 100 megabytes to compensate for the 200 megabyte memory above the bar storage. As you can see this HelloWorld example was successful with the smaller Java heap size.

> java -Xmx100M HelloWorld
Hello World

64 bit Java -Xcompressedrefs and -Xlp Options

As mentioned above, the 64 bit java command provides two options that can significantly improve performance. The compressed references and large pages features were added to the IBM Developer Kit for Java 6, 64-bit edition, J9 Java virtual machine (JVM) and Just-in-Time (JIT) compiler to provide relief for memory footprint growth incurred when migrating from a 31-bit JVM to a 64-bit JVM. This growth in footprint typically increases system memory requirements while also regressing throughput performance. Using the compressed references and large pages features provides 64 bit Java performance that may be equal to 31 bit Java performance for some applications.

Hints: The -Xcompressedrefs with a 2048 megabyte heap size is a performance sweet spot, which may be a good starting point when tuning a 64 bit Java application for the first time. Also note that even though you may specify the -Xlp option, it is possible that Java may use the smaller 4096 byte pages, when large pages are either not configured or not enough large pages are available.

The following white paper shows that it is possible to recover the 31-bit footprint and throughput performance using these 64-bit new options and heap sizes up to 30 GB. This paper also reviews the advantages and disadvantages of using 31-bit SDK and 64-bit SDKs, provide a brief implementation overview, and discuss the performance characteristics of various combinations of heap sizes and Java options. All developers are encouraged to read through this article, but the intended audience is enterprise application developers who are deploying Java workloads on the IBM System z10 mainframe.

Examples Using -Xcompressedrefs and -Xlp

This example below uses the sweet spot of 2 Gigabyte heap size ( -Xmx2048m ) with Compressed References. The -verbose:gc option shows that the compressedRefsShift value is zero. This means that zero shifts are required when converting the 4 byte compressed reference addresses to 8 bytes. This zero shifts is why this is a performance sweet spot. Also note that compressedRefs value= true, which means compressed references are enabled.

> java -verbose:gc -Xcompressedrefs -Xmx2048m -Xms2048m HelloWorld
 
<initialized>
  <attribute name="gcPolicy" value="-Xgcpolicy:optthruput" />
  <attribute name="maxHeapSize" value="0x80000000" />
  <attribute name="initialHeapSize" value="0x80000000" />
  <attribute name="compressedRefs" value="true" />
  <attribute name="compressedRefsDisplacement" value="0x0" />
  <attribute name="compressedRefsShift" value="0x0" />
  <attribute name="pageSize" value="0x1000" />
  <attribute name="requestedPageSize" value="0x1000" />
</initialized>

In the next example a 3Gigabyte heap size is used. In this example you see a compressedRefsShift value of 1 is shown. This means a shift by 1 instruction must be performed every time a 4 byte compressed reference address is converted to 8 bytes.

> java -verbose:gc -Xcompressedrefs -Xmx3072m -Xms3072m HelloWorld

<initialized>
  <attribute name="gcPolicy" value="-Xgcpolicy:optthruput" />
  <attribute name="maxHeapSize" value="0xc0000000" />
  <attribute name="initialHeapSize" value="0xc0000000" />
  <attribute name="compressedRefs" value="true" />
  <attribute name="compressedRefsDisplacement" value="0x0" />
  <attribute name="compressedRefsShift" value="0x1" />
  <attribute name="pageSize" value="0x1000" />
  <attribute name="requestedPageSize" value="0x1000" />
</initialized>

The large page example below shows the option -Xlp for large 1 megabyte pages is specified. Here you can see that the requested PageSize value of 0x100000 was requested but the pageSize value=0x1000 or 4096 bytes were actually used. Its possible other JVM processes were using all the system wide configured large pages or large pages were never configured on this system. Although large pages were not used, the program HelloWorld ran successfully with 4096 byte pages.

> java -verbose:gc -Xlp HelloWorld

<initialized>
  <attribute name="gcPolicy" value="-Xgcpolicy:optthruput" />
  <attribute name="maxHeapSize" value="0x20000000" />
  <attribute name="initialHeapSize" value="0x400000" />
  <attribute name="compressedRefs" value="false" />
  <attribute name="pageSize" value="0x1000" />
  <attribute name="requestedPageSize" value="0x100000" />
</initialized>

Hello World
</verbosegc>

Shared Classes Group Access Examples

On Linux®, AIX®, z/OS®, and i5/OS® platforms, if multiple users in the same operating system group are running the same application, use the groupAccess suboption, which creates the cache allowing all users in the same primary group to share the same cache. If multiple operating system groups are running the same application, the %g modifier can be added to the cache name, causing each group running the application to get a separate cache.

Note in the example below two shared classes are created. One that is shared with other JVMs in the same group and another that is shared with with JVM using the same user ID.

> java -Xscmx8m -Xshareclasses:groupAccess,name=%gcache5 HelloWorld
Hello World

> java -Xscmx8m -Xshareclasses:listAllCaches
Shared Cache       OS shmid      in use      Last detach time
DEPTD60cache5      73739         0           Fri Mar  2 13:59:01 2007

> java -Xscmx8m -Xshareclasses:groupAccess,name=cache5 HelloWorld
Hello World

> java -Xscmx8m -Xshareclasses:listAllCaches
Shared Cache       OS shmid      in use      Last detach time
DEPTD60cache5      73739         0           Fri Mar  2 13:59:01 2007

cache5             204810        0           Fri Mar  2 14:01:40 2007

> id
uid=258(TESTER) gid=0(DEPTD60

Performance

For developing and running applications


Garbage Collection

One of the great benefits of the Java platform is that it takes care of much of the work of garbage collection for you, but there are occasions when you still want to tweak the way garbage collection takes place. With the latest Java technology implementation from IBM, you can choose among several garbage collection policies and tune the size of your heap to help obtain the optimal performance out of your application.

For a better understanding about Java Garbage collection policies see the following links:
Java technology, IBM style: Garbage collection policies, Part 1
Java technology, IBM style: Garbage collection policies, Part 2

The IBM Monitoring and Diagnostic Tools for Java™ - Garbage Collection and Memory Visualizer is designed to help diagnose and analyze memory-related Java performance problems. For more details see the following link:
Java diagnostics, IBM style, Part 2: Garbage collection with the IBM Monitoring and Diagnostic Tools for Java - Garbage Collection and Memory Visualizer

For 64 bit Java applications, Java 6 provides the -Xcompressrefs option, which will significantly reduce the size of the Java heap storage required. See the section on 64 Bit Java.


JVM

The following is a list of performance suggestions for the Java Virtual Machine (JVM) runtime environment:


z/OS UNIX System Services (USS)

The JVM uses UNIX System Services for z/OS (USS) for base operating system functions. For this reason, USS must be correctly installed and tuned in order to get optimum performance from the JVM. See USS performance  for detailed tuning suggestions.

For additional information, see:

A number of Unix based tools for z/OS are available for free via download. Some of these are Java specific. These tools were designed for OS/390 UNIX, by IBM developers and testers. There are no warranties of any kind, and there is no service or technical support available for these from IBM. See the z/OS UNIX Tools .


Applications and Environments

For developing and running your applications in z/OS


Java Interoperability: support for Java 5 and Java 6

In V4.2, Enterprise COBOL applications using object-oriented syntax for Java interoperability can now run with Java 5 or Java 6. See the Cobol references below:
http://www-01.ibm.com/software/awdtools/cobol/zos/library/


ASCII to EBCDIC

One important aspect of the System z environment that can sometimes raise portability issue with Java code is that z/OS uses the EBCDIC character encoding instead of the more common ASCII. Within the scope of the JVM, all character and string data is stored and manipulated in Unicode, and I/O data outside of the virtual machine (disk, network, and so forth) is converted to the native platform encoding. However, Java applications that implicitly assume ASCII in specific situations might require some alterations to run as expected under z/OS.

There are a number of environmental tricks that are often useful to test whether implicit ASCII assumptions are in effect. For instance, for config files read in during start-up (or other 'adminstrative' file manipulation), you can use a simple command-line utility to convert those files to the appropriate encoding that you require.

In some cases, changing JVM properties can also allow successful functionality tests, but because this can produce other side effects, the long term solution is sometimes best addressed in code. The Java language contains the abstractions necessary to handle the switch between character encodings. Most important are the various Reader and Writer classes in the java.io package, which provide alternate constructors with a specified codepage. This mechanism is used for internationalization support, and it can also be used to force ASCII (or other) I/O where required. It is important to consider that all I/O does not need to be overridden; for example, character output to the display should remain in the native encoding.

In addition to the Reader and Writer classes, there are a few specific situations that might require additional care. For example, there is an overloaded getBytes() method in the String class that takes an encoding as an additional parameter. This is useful for direct string manipulation when implementing custom data streams or network protocols directly in Java.

Some Java applications explicitly assume ASCII encoding and therefore require some alterations to run as expected under OS/390. For example, a platform neutral application might have hard coded dependencies, such as literals in ASCII.

In general, straightforward workarounds are available for character encoding problems. Some encoding problems are not visible to the application because they are handled within products running on OS/390. An example of this is Java Database Connectivity (JDBC).

It is often best to deal with codepage issues by running the JVM with default encoding of ASCII (-Dfile.encoding=ISO8859-1) and then to specifically call out the codepage that you need when you are writing to MVS files and datasets that are in EBCDIC. This makes porting of code easier, which is a reason Websphere now runs this way.

For your information, the JZOS function now incorporated into z/OS Java SDK5 and SDK6 products may also help in ASCII-EBCDIC questions. The JZOS ZUtil class has a method "getDefaultPlatformEncoding()" that returns the EBCDIC codepage that is being used by the process running the JVM. Also, the FileFactory class can be used to read and write text files - if the file is a //DATASET name then JZOS uses this encoding under the covers automatically.

For more information, see JZOS Java Launcher and Toolkit Overview .


JAR file considerations

A jar is an archive of files used by a java applet. Many or all of the files that an applet needs can be combined into a single jar file, which an appletviewer can download in a single http request.

We expect that jar files downloaded from other platforms will contain text data in ASCII (8859-1), and therefore have enabled the appletviewer to expect text files in a jar file to be in ASCII. This means however, that if the jar tool is used on z/OS to create a jar file, then text files must be converted to ASCII before being added. Of course this also means that any jar files you create on z/OS can be transported and used on other platforms. Equally, any text files extracted from a jar file will not be converted from their original encoding.


Language Environment (LE)

The JVM uses LE for runtime language services. More information can be found at the LE  website. For additional Java information, see Java and LE runtime options


Troubleshooting

Helpful hints about what you can do if you have a problem


IBM JVM Diagnostics Guides

Diagnostics Guides are available. The diagnostics guide tells you about the way the IBM Virtual Machine for Java works, debugging techniques, and the diagnostics tools that are available to help you solve problems with Java Virtual Machines.

These guides include sections on the garbage collector, the JIT compiler, the class loader, the ORB and covers many aspects of problem determination in all the supported platforms.

They also reflect changes to the JAVA_DUMP_OPTS environment variable that are introduced into this service refresh, including suppression of dumps.

Information on fonts for z/OS Java product is available to provide some guidance. There have been occasional questions about usage of customer provided fonts with the z/OS Java product.