Java is an object oriented language, so it creates objects in storage, Generally a lot of objects.
What is more, Java provides automatic garbage collection (GC), which means that some time after an object is no longer able to be accessed by any running Java code, the Garbage Collector will make sure it is deleted.
The IBM i server allows the amount of real (as opposed to virtual) memory to be specified by a Memory Pool.
Page faults occur whenever the actual size of your GC heap, and any other programs using memory from that pool if the pool is shared, exceed the amount of real memory specified in the pool.
Excessive page faults may occur if the memory pool for your JVM is too small.
These faults will be reported as non-database page faults on the WRKSYSSTS command display.
Typically, the storage pool for your JVM is *BASE.
Fault rates between 20 and 30 per second are generally acceptable, but higher rates should be reduced by increasing memory pool size.
In some cases, reducing this value below 20 or 30 per second may improve performance as well.
Lowering the GCHINL parameter might also reduce paging rates by reducing the i5/OS JVM heap size, but may also cause some performance problems due to more frequent GC cycles.
A memory pool also has an activity level associated with it which specifies the number of threads that can actively use processor(s) at the same time from that memory pool.
When more threads are started than are allowed to concurrently execute due to the activity level control, the excess threads will be forced to wait for an available activity level slot before they can run.
The number of threads running (active threads) refers to the number of threads that are eligible to compete for a processor and that count against the activity level for a memory pool.
Active threads do not include threads that are waiting for input, for a message, for a device to be allocated, or for a file to be opened.
Active threads do not include threads that are ineligible (threads that are ready to run but the memory pool activity level is at its maximum).
Once the maximum activity level for a memory pool has been reached, additional threads needing the memory pool are placed in the ineligible state.
The threads wait in ineligible state for the number of active threads in the memory pool to fall below the maximum activity level, or for a thread to reach the end of its time slice.
As soon as a thread gives up its use of the memory pool, the other threads that are not active become eligible, and will be dispatched based on their priority.
Having Java threads in the ineligible state can cause severe performance degradation as well as excessive JVM GC heap growth.
When the Java threads are in the ineligible state they are unable to communicate with the Garbage Collector, which will prevent a Java GC cycle from completing.
This will cause the GC heap to grow rapidly, which will tend to drive the pool into page thrashing, and further degrade performance.
In order to avoid this condition, set the activity level of the memory pool to at least as large as the maximum number of threads you expect to be concurrently active at any time for the JVM running in the memory pool.