IBM i - DUMP JVM

Another tool that can be used to learn about garbage collector performance is the Dump JVM (DMPJVM) command, which provides a spool file with information about your JVM, including some of the key GC data -- initial heap size, maximum heap size, current heap size and number of collections since the JVM was started.

It also includes a dump of the objects currently in the heap, which can be helpful for analyzing object leak problems. (Object leaks occur when your application creates new objects and keeps a reference to the objects even when they're no longer needed, preventing the collector from collecting them.

Sample of the GC section of DMPJVM output:

 

Garbage collector parameters

Initial size: 262144 K

Max size: 240000000 K

Current values

Heap size: 449952 K

Garbage collections: 278

Additional values

JIT heap size: 85728 K

JVM heap size: 186588 K

Last GC cycle time: 1302 ms

 

While the DMPJVM data is only a snapshot and doesn't provide the details available with verbose GC, it can be run without restarting your JVM, so it's useful for getting some information about the JVM after a problem has occurred.

Search the IBM Support Knowledge Center for information about genjvmdmp or jvmdmp

Use WRKACTJOB command to locate the JSM JVM job.

 

JSM 

JSMJOB         QOTHPRDOWN     BCH    .0     PGM-RUNJSM     TIMW 

QJVACMDSRV     QOTHPRDOWN     BCI    .0                    TIMW

 

Job: QJVACMDSRV     User: QOTHPRDOWN Number: 422841

 

Use DMPJVM command to create a spool file with the JVM dump information.

 

DMPJVM JOB (422841/QOTHPRDOWN/QJVACMDSRV)

 

Sample DMPJVM on the JSM JVM:

 

Java Virtual Machine Information  422841/QOTHPRDOWN/QJVACMDSRV              

........................................................................

Classpath

........................................................................ 

java.version=1.2

/QIBM/ProdData/Java400/jdk12/lib/jdkptf12.zip:/QIBM/ProdData/Java400/jdk12/lib/rt.jar:/QIBM/ProdData/Java400/jdk12/lib/i18n.jar:/QIBM/ProdData/Java400/ext/IBMmisc.jar:/QIBM/ProdData/Java400/ext/jssl.jar:/QIBM/ProdData/Java400/ext/ibmjssl.jar:/QIBM/ProdData/Java400/:./classes:./jar/activation.jar:./jar/jsm.jar:./jar/jsmnative.jar:./jar/mailapi.jar:./jar/pop3.jar:./jar/smtp.jar:./jar/xalan.jar:./jar/xerces.jar:./jar/xlrd.jar:./jar/jsmservice.jar:./jar/jsmutil.jar:./jar/mail.jar:

........................................................................

Garbage Collection

........................................................................

Garbage collector parameters 

Initial size: 2048 K

Max size: *NOMAX 

Current values 

Heap size: 44032 K

Garbage collections: 51 

........................................................................

Thread information

........................................................................

Information for 4 thread(s) of 4 thread(s) processed

Thread:  00000001 Thread-0 

TDE:  B000100007CCA000

Thread priority: 5

Thread status: Running

Thread group: main

Runnable: java/lang/Thread 

Stack: 

java/net/PlainSocketImpl.accept(Ljava/net/SocketImpl;)V+1 (PlainSocketImpl

java/net/ServerSocket.implAccept(Ljava/net/Socket;)V+36 (ServerSocket.java 

java/net/ServerSocket.accept()Ljava/net/Socket;+8 (ServerSocket.java:224)

com/lansa/jsm/d.if()Lcom/lansa/jsm/a;+0 (:0)

com/lansa/jsm/JSMManager.do(Ljava/lang/String;)V+0 (:275)

com/lansa/jsm/JSMManager.main([Ljava/lang/String;)V+0 (:311) 

 Locks: 

None 

Thread:  00000002 Reference Handler 

TDE:  B0001000070D4000

Thread priority: 10

Thread status: Waiting

Wait object: java/lang/ref/Reference$Lock

Thread group: system

Runnable: java/lang/ref/Reference$ReferenceHandler 

Stack: 

java/lang/ref/Reference$ReferenceHandler.run()V+48 (Reference.java:129) 

Locks: 

None 

Thread:  00000003 Finalizer 

TDE:  B000100007CCE000

Thread priority: 8

Thread status: Waiting

Wait object: java/lang/ref/ReferenceQueue$Lock

Thread group: system

Runnable: java/lang/ref/Finalizer$FinalizerThread 

 Stack: 

java/lang/ref/ReferenceQueue.remove(J)Ljava/lang/ref/Reference;+48 (Refere 

java/lang/ref/Finalizer$FinalizerThread.run()V+3 (Finalizer.java:190)

Locks: 

None 

 

Once you've picked a reasonable starting point, start your application and let it run for a while under the maximum load that you intend to handle, giving it time to reach a steady state (a few minutes is usually sufficient). It's best to use a load-generation tool to put a constant load on your system. This allows you to tune your application in a development environment rather than a production environment.

In addition to providing a constant load (allowing you to see the effects of changes more accurately), this allows you to make changes as necessary without affecting users.

While your application is running, use the aforementioned tools to measure the impact of your changes. Your load-generation tool should also detail the throughput and response time so you can see the impact on your application's performance.

Whenever you change performance parameters such as the GC threshold, you should measure the effects on throughput and/or response time to ensure that the changes actually help. If the tools indicate that there's still room for improvement, change the threshold and try a new run. Once you've increased it too far, the throughput begins to degrade again, indicating that you must reduce the threshold.

These recommendations are based on the assumption that your system has enough main storage to handle larger heap sizes. In reality, this may not always be the case.

In systems with limited memory, it may be necessary to set the GC threshold to a lower value, which increases collection frequency and decreases heap size. This allows the entire heap to be kept in memory.

Use Work with System Status (WRKSYSSTS) command to monitor the non-database paging/faulting rates.

If these rates get too high, the heap may be too large. The definition of "too large" depends on a variety of factors--system size, number of disks and system workload--but sustained non-database paging rates greater than 10 faults per second by Java programs is generally cause for concern.

Higher paging rates are acceptable during "warm-up" periods.

High paging rates may result from having the GC threshold set too high or may be a symptom of a larger problem.

In this case, the first step should be to isolate the JVM in its own memory pool.

This reduces the effects that other applications may have on the JVM and makes it easier to identify whether the problem is with the GC settings, system configuration or simply not enough hardware to handle the workload.

In cases where memory is especially limited, it may be useful to set the maximum heap size.

Normally, this should be left at the default value *NOMAX, which means that GC runs only when the GC threshold has been reached.

If a maximum heap size is set, the collector runs whenever the heap reaches that maximum size.

However, unlike a normal GC, if the maximum size is reached, all application threads must wait until the collector has finished before they can continue running. This results in undesirable pause times.

Therefore, it's preferred to use the maximum heap size as a safety net to handle times of unexpected heap growth and ensure that the heap doesn't grow larger than the available memory.

The GC threshold should be set so that this maximum size is never actually reached under normal circumstances.

Tuning the collector is one way to reduce the amount of time spent in GC. Another way is to reduce the number of objects being created. (Note: Tips for reducing object creation are common to all platforms and documented in several places.