IBM Support

Technique for Increasing Available Native Memory on AIX 32-bit Java

Question & Answer


Question

If you are seeing native OutOfMemoryError problems on AIX 32-bit, how can you increase the available native memory?

Cause

Native memory is the term used to distinguish the memory available to the JVM from the Java heap that a Java application uses. All virtualized resources, including the Java heap and Java threads, are stored in native memory, with the data used by the JVM as it runs. This memory is called the native heap. The native heap contains resources for the JVM itself; for example, the Just-In-Time Compiler, Classes, and ClassLoaders, as well as for the Java application. The memory in which the Java process runs is called the process address space. This memory area is shared by both the Java and native heaps. The limitations on the total size of the process address space, and the amount of memory available to the Java heap and native heap is imposed by the operating system and the hardware.

Answer

If you are using the 32-bit IBM JVM on AIX >= 5.2, and you are experiencing native OutOfMemoryErrors, and your maximum heap size (-Xmx) is less than 2304MB, and you cannot lower your maximum heap size or use other techniques to get more native memory, then you may benefit by explicitly changing the AIX memory model (LDR_CNTRL=MAXDATA) for affected processes to 0XB0000000@DSA. This change increases the theoretical native memory per process by three segments or 756MB. However, typically, this change increases available native memory per process by about 400MB to 600MB. This change does not affect the performance of the JVM; however, the change does come at the cost of loading all shared libraries privately into native memory segments. If you change X JVMs on one machine to the 0xB@DSA memory model, then the total virtual memory usage of that machine may increase by up to (N*(X-1)) MB, where N is the size of the shared libraries' code and data. Typically for stock WebSphere Application Server, N is about 50MB to 100MB.

To change the memory model in WebSphere Application Server, go to the Admin Console -> Application Servers -> $SERVER -> Java and Process Management -> Process Definition -> Environment Entries
  1. Click New. Name: LDR_CNTRL Value: MAXDATA=0XB0000000@DSA
  2. Click OK
  3. Click New. Name: IBM_JVM_LDR_CNTRL_NEW_VALUE Value: MAXDATA=0XB0000000@DSA
  4. Click OK
  5. Save, synchronize, and restart


IBM_JVM_LDR_CNTRL_NEW_VALUE is not strictly required but should be set to alleviate potential confusion.

There are two ways to determine the size of the shared libraries' code and data:

  1. using svmon and
  2. using a system dump and dbx. Both of these methods can also help determine native memory segment usage.
     

Method #1: Using svmon

This method assumes a recent version of the JVM, and that LDR_CNTRL has not been explicitly set, and that -Xmx is less than 2304MB. In this case, the JVM will have automatically chosen MAXDATA=0XA0000000@DSA in which shared library code are in segment 0xD and shared library data are in segment 0xF (see http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/topic/...... aix_mem_32_default.html and More Links at the bottom).

Execute the following command to gather a snapshot of virtual address space segment usage (you may need root access): svmon -rmP $PID

Find the rows with the Esid column value of 'd' or 'f'. Note the PSize column for each ('s', 'm') and map this to the PageSize at the top of the svmon output (4KB, 64KB, respectively). For both segments, on the next line with "Addr Range: X..Y," calculate (Y+1)*PageSize.


Method #2: Using a system dump and dbx

Ensure that "Enable full CORE dump" and ulimits are properly set (see http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/topic/....aix_setup_full_core.html). This is often done by editing /etc/security/limits and adding stanzas for the user that runs WebSphere, setting core=-1, nofiles=-1, data=-1, and fsize=-1, and restarting the JVMs.

Gather a system dump using the non-destructive "gencore $PID $CORE_NAME" command or the destructive "kill -6 $PID" or "kill -11 $PID" commands.

If you will be analyzing the core on the same machine with dbx, then find the full path to the Java executable for that PID (for example, using "ps -elf | grep $PID" and taking the first part of the CMD column), and execute the command "dbx $JAVA_EXE_PATH $CORE_PATH". Ensure that there are no errors or warnings starting dbx (such as "warning: The core file is not a fullcore"). Run the command "coremap" (you may also pipe the output to a file using "coremap > coremap.txt" then quitting using "quit" and analyzing the output file normally). For each "Mapping: Loaded Module Text" and "Mapping: Loaded Module Data" line, take the size value from that line, convert from hexadecimal into decimal, and sum the values. This may be less precise than svmon.

If you will be analyzing the core on a different machine, run jextract on the core which will package all the libraries along with the core: <WAS>/java/jre/bin/jextract $CORE_PATH. This will produce a .zip file. Extract the .zip file on the target machine, and run dbx as above, passing the Java executable in the ZIP along with the option -p /usr=./usr:/opt=./opt... to account for the location of the libraries in the ZIP.

Note: The other effect of changing to the 0xB@DSA memory model is that segment 0xE is no longer available for mmap/shmat, but instead those allocations grow down in the same way as the Java heap. If your -Xmx is a multiple of 256MB (1 segment), and your process uses mmap/shmat (for example, client files), then you will have one less segment for native memory. This is because native memory allocations (malloc) cannot share segments with mmap/shmat (Java heap, client files, etc.). To fully maximize this last segment for native memory, you can calculate the maximum amount of memory that is mmapped/shmatted at any one time using svmon (find mmapped sources other than the Java heap), and then subtract this amount from -Xmx. -Xmx is not required to be a multiple of 256MB, and making room available in the final segment may allow the mmapped/shmatted allocations to be shared with the final segment of the Java heap, leaving the next segment for native memory.

More Links:
https://www.ibm.com/developerworks/java/library/j-nativememory-aix/
http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/topic/......aix_auto_ldr_cntrl.html
http://publib.boulder.ibm.com/infocenter........._1vg000121410cbe-1195c23a635-7ffa_1001.html
http://publib.boulder.ibm.com/infocenter/javasdk/.....aix_ldr_cntrl_page_sizes.html
http://publib.boulder.ibm.com/infocenter/aix/v6r1/.......svmon.htm

[{"Type":"MASTER","Line of Business":{"code":"LOB45","label":"Automation"},"Business Unit":{"code":"BU059","label":"IBM Software w\/o TPS"},"Product":{"code":"SSEQTP","label":"WebSphere Application Server"},"ARM Category":[{"code":"a8m50000000CdArAAK","label":"WebSphere Application Server traditional-All Platforms-\u003EOutOfMemory-\u003ENative-\u003EOther"}],"ARM Case Number":"","Platform":[{"code":"PF002","label":"AIX"}],"Version":"8.0.0;8.5.5;9.0.5"}]

Document Information

Modified date:
03 October 2022

UID

swg21450144