Calculating storage requirements for JVM servers

To run a JVM server successfully in a CICS® region, you must ensure that enough free MVS™ storage is available for both the JVM and its deployed applications to use.

About this task

The storage that is required for a JVM server, and the Java™ applications in it, does not come from CICS-managed storage areas such as the DSA, EDSA, or GDSA. Some storage areas are managed by the Language Environment® handling requests, such as malloc() issued by C code. The remaining storage areas are managed directly by the JVM, by using z/OS® storage management requests such as IARV64. Both of these storage area management types use storage from the available MVS private areas. It is important to ensure that sufficient non-allocated private area region storage is available in the 24-bit, 31-bit, and 64-bit addressing areas. CICS cannot use its short-on-storage mechanism when private area region storage is running low.

The major Java components that allocate MVS storage areas are as follows:
  • Java heap
  • Loading of Java classes
  • JIT compilation caches
  • Native stack
  • Java monitors
  • Java threads
  • UNIX shared libraries

The Java heap is a contiguous pre-allocated block of 64-bit storage that is used to store the runtime data area for all objects and arrays. It is managed by the JVM garbage collection process, and its size can only be modified if the JVM is restarted. The other JVM storage areas are more dynamic in size and their size can vary depending on usage. In addition, on top of the storage areas that are allocated by the JVM, you must also consider other components that use MVS private area and interact with the JVM such as JDBC type 2 drivers, IBM® MQ Java adapter, or third-party tools.

To estimate the amount of storage used by the JVM in the different MVS private storage areas, you can use the following procedure.

Note: The following procedure is valid only if the MVS private area is maximized by setting the z/OS parameter REGION as 0M.

Procedure

  1. Calculate your 24-bit storage.

    Each JVM thread requires 4 KB of 24-bit storage. A single JVM server can start more than 50 background daemon threads; this number does not include the number of CICS-managed JVM server threads defined by the JVMSERVER THREADLIMIT attribute. If you are using a Liberty JVM server, the number of daemon threads can be 100 or greater.

    UNIX System Services temporarily requires 256 KB of contiguous 24-bit storage during the process of creating a new thread. The minimum 24-bit requirement is calculated as follows:

    256KB + (4KB * number_of_threads)
  2. Calculate your 31-bit storage.

    Multiple JVM components can allocate storage from the 31-bit MVS private area that includes loading of Java classes, CICS control blocks, Java thread stack, the JIT compiler, and the USS dynamic link library (DLL) files used by the JVM.

    1. Java class loading

      By default, CICS JVM servers with -Xmx (heap) values of 57GB or less use Java compressed references. Compressed references instruct the JVM to create smaller objects, and having smaller objects can improve performance. Using compressed references causes the Java objects, classes, threads, and monitors to be loaded into the LE HEAP31 storage area in 31-bit storage. If you have insufficient space in 31-bit storage, class loading fails, causing termination of the JVM. Setting the JVM command line option –Xnocompressedrefs disables the use of compressed references and instead loads the Java classes into 64-bit storage.

    2. JIT Compiler

      The JIT compiler is responsible for continuous optimization, by compiling Java byte code. Executable code is stored in the JIT code cache, and static data is stored in the JIT data cache. Prior to z/OS, Version 2 Release 3 and Java 8 SR5 the code cache is stored in 31-bit storage, whereas the data cache is stored in 64-bit storage. Depending on the number of Java applications, and the amount of JIT activity, the 31-bit JIT code cache can expand dynamically to a maximum size determined by the JVM setting -Xcodecachetotal. This defaults to 128 MB. If the cache becomes full, the JIT process stops but the JVM continues to operate with reduced potential performance. If you are using z/OS, Version 2 Release 3, you can free up more space in the 31-bit private area by upgrading to Java 8 SR5, which supports residency mode for 64-bit applications (RMODE64) for the JIT code cache. This stores the compiled JIT code in the 64-bit private area.

    3. UNIX shared libraries

      The shared library region is a z/OS® feature that enables address spaces to improve the performance of the loading of UNIX System Services dynamic link library (DLL) files, and to share the associated real storage. The shared library function is disabled by default in CICS JVM servers, but is supported by the IBM Java SDK. When the first JVM process that uses shared libraries is started in the region, the shared library region reserves storage in the 31-bit high private area.

      For more information, see Tuning the z/OS shared library region.

      Note:

      As an approximate guideline if using Java 8 SR5 and a single application, the first JVM server to start within a CICS region can allocate anywhere between 51M to 115M of 31-bit MVS private area depending on configuration and workload.

      The subsequent JVM servers have a lower footprint and can allocate anywhere between 8M and 73M, as the JVM DLL files need to only be loaded once.

      These figures do not include the UNIX shared library region, the value of which must also be added to the 31-bit storage if enabled.

  3. Calculate your 64-bit storage.

    Multiple JVM components can allocate storage from the 64-bit MVS private area that includes the Java heap, native thread stack, Java classes, JIT compiler output, and Java monitors. The amount of 64-bit storage that is required can be estimated as a minimum of 2 GB, with additional storage required for larger workloads or more complex configurations.

    To more accurately estimate 64-bit storage, you need to consider:
    • The maximum Java heap value, set by using -Xmx
    • The maximum number of all threads in the JVM. Each thread requires a minimum of 3 MB of Language Environment stack storage, including 1 MB of stack. This accounts for the minimum 1 MB native stack storage, 1 MB of reserve storage and the 1 MB Language Environment control block that is required to support each thread. See Identifying Language Environment storage needs for JVM servers
    • Storage for the Java classes, JIT caches, and Language Environment 64-bit heaps. You can add a best guess of 300 MB - 500 MB depending on workload and configuration
    Note:

    The Java shared class cache uses UNIX shared memory which does not count towards the CICS region's address space MEMLIMIT.

    The resulting figure needs to be rounded up to the next GB to account for the way that CICS GDSA expansion views guarded storage.

  4. Run the sample statistics program DFH0STAT to provide values used to estimate MVS storage.
    • Note the value for  1  Private Area storage available below 16 Mb, which is the currently available 24-bit private storage in the region.
    • Note the value for  2  Private Area storage available above 16 Mb, which is the currently available 31-bit private storage in the region.
    • Note the value for  3  MEMLIMIT minus usable within Private Memory Objects, which is the currently available 64-bit private storage in the region.
    Storage BELOW 16MB                                                     
    __________________                                                     
      Private Area Region size below 16Mb . . . . . . . . :      10,216K   
        Max LSQA/SWA storage allocated below 16Mb (SYS) . :         660K   
        Max User storage allocated below 16Mb (VIRT). . . :       5,460K   
        System Use. . . . . . . . . . . . . . . . . . . . :          20K   
        RTM . . . . . . . . . . . . . . . . . . . . . . . :         250K   
      __________________________________________________________________   
      Private Area storage available below 16Mb . . . . . :       3,826K    1 
    
    Storage ABOVE 16MB                                                    
    __________________                                                    
      Private Area Region size above 16Mb . . . . . . . . :   1,417,216K  
        Max LSQA/SWA storage allocated above 16Mb (SYS) . :      84,500K  
        Max User storage allocated above 16Mb (EXT) . . . :     987,936K  
      __________________________________________________________________  
      Private Area storage available above 16Mb . . . . . :     344,780K   2 
    
    Storage ABOVE 2GB   
    _________________________  
      MEMLIMIT Size. . . . . . . . . . . . :               15,360M    
      MEMLIMIT Set By. . . . . . . . . . . :                  JCL 
      
      Current Address Space active (bytes) :      1,143,996,416    
      Current Address Space active . . . . :             1,091M    
      Peak Address Space active. . . . . . :             1,091M       
         
      MEMLIMIT minus Current Address Space active. . . . . . . :          14,269M     3 
      MEMLIMIT minus allocated to Private Memory Objects . . . :          13,144M
      MEMLIMIT minus bytes usable within Private Memory Objects:          14,269M 
      Number of Private Memory Objects . . . . . . . . . . . . :               33 
        ....minus Current GDSA extents . . . . . . . . . . . . :               32 
      Bytes allocated to Private Memory Objects. . . . . . . . :           2,216M  =       2,323,644,416
        ....minus Current GDSA allocated . . . . . . . . . . . :           1,192M  =       1,249,902,592
      Bytes hidden within Private Memory Objects . . . . . . . :           1,125M  =       1,179,648,000
        ....minus Current GDSA hidden. . . . . . . . . . . . . :           1,124M  =       1,178,599,424
          ....minus CICS Internal Trace Table hidden . . . . . :             130M 
      Bytes usable within Private Memory Objects . . . . . . . :           1,091M  =       1,143,996,416
      Peak bytes usable within Private Memory Objects  . . . . :           1,806M  =       1,893,728,256
      Current GDSA Allocated . . . . . . . . . . . . . . . . . :           1,024M  =       1,073,741,824
      Peak GDSA Allocated. . . . . . . . . . . . . . . . . . . :           1,024M 
    
  5. Start the JVM server and run a representative Java workload.
    Observe how the values for each private storage area available change, and make sure that the private storage areas are not constrained.