Home  > Resources  > Blog

Generational GC in IBM JDK

 
June 23, 2010 by Bibhas Bhattacharya
Category: Java

IBM JDK 1.5 introduced the use of generational GC. Prior to that, the whole heap was divided into Large Object Area (LOA) and Small Object Area (SOA). No consideration was given to the age of an object.

Generational GC attempts to minimize the number of objects to be inspected during GC. It takes into account the age of the objects. The mechanism is similar to the generational GC of Sun HotSpot and JRockit. There are slight differences.

Enabling Generational GC

Generational GC is not enabled by default in IBM JDK 1.5. To enable it, use the gencon GC policy. This is done by adding the following command line argument.

-Xgcpolicy:gencon

Heap Partitions

Partitioning the heap in regions is key to minimizing the number of objects to be inspected during GC. When generational GC is enabled, the heap is divided into two spaces:

  1. The new space.
  2. The tenured space.

The new space is further divided into two zones:

  1. Allocate space.
  2. Survivor space.

image

 

Initially, the survivor space is completely empty. A new object is always created in the allocate space.

image

If when creating a new object an allocation failure takes place in the allocate space, a minor GC called scavenge is started. Scavenge works as follows.

image

All live objects from the allocate space are moved to the survivor space. The allocate space becomes completely empty of any live objects. The roles of the allocate and survivor spaces are then switched.

image

New objects are then created in the new allocate space.

If during scavenge, it is detected that a live object to be moved from the allocate space has survived N number of previous scavenge attempts, the object is moved to the tenured space instead. Where N is called the tenure age and is dynamically determined by the JVM.

image

It is expected that if an object has survived multiple scavenge attempts, it is probably a long lived object. There not much point is inspecting that object during every GC. By moving that object to the tenured space we reduce the number of objects to be inspected during a scavenge.

If after a scavenge and allocation failure continues in the new allocate space, the new area is grown.

If during tenuring, the tenured space has allocation failure a GC of the tenured space will be needed.

Setting Sizes

The –Xms and –Xmx options continue to set the total initial and maximum sizes of the heap.

To set the initial and maximum sizes of the new space, use the –Xmns and –Xmnx options. For example:

-Xms5m  -Xmns2m

The total initial heap size is 5MB. Out of which 2MB will be for new space. The remaining 3MB will be for the old space.

You can also set the initial and maximum size of the tenured (old) space using –Xmos and –Xmox. But, avoid setting both new and tenured space sizes. It is best to set the size of one space and let the system use the remaining heap for the other space.

To view the current sizes of various spaces, use the –verbose:sizes option. For example:

-verbosegc -Xms5m -Xgcpolicy:gencon -verbose:sizes –Xmns2m

This will output:

-Xmca32K        RAM class segment increment  
-Xmco128K       ROM class segment increment
-Xmns2M         initial new space size  
-Xmnx253764K    maximum new space size  
-Xms5M          initial memory size
-Xmos3M         initial old space size
-Xmox1015058K   maximum old space size
-Xmx1015058K    memory maximum
-Xmr16K         remembered set size
-Xmso32K        operating system thread stack size
-Xiss2K         java thread stack initial size
-Xssi16K        java thread stack increment
-Xss256K        java thread stack maximum size 

Understanding Generational Verbose GC Output

When a scavenge is performed, only the new or nursery area is collected. The verbose GC output looks like this.

<af type="nursery" id="1" timestamp="Jun 22 22:46:35 2010" intervalms="0.000"> 
  
  <minimum requested_bytes="16" />
  <time exclusiveaccessms="0.014" meanexclusiveaccessms="0.014" threads="0" lastthreadtid="0x00172F00" />
  <refs soft="3" weak="6" phantom="1" dynamicSoftReferenceThreshold="32" maxSoftReferenceThreshold="32" />
  <nursery freebytes="0" totalbytes="1048576" percent="0" />
  <tenured freebytes="3029168" totalbytes="3145728" percent="96" >
    <soa freebytes="2871984" totalbytes="2988544" percent="96" />
    <loa freebytes="157184" totalbytes="157184" percent="100" />
  </tenured>
  <gc type="scavenger" id="1" totalid="1" intervalms="0.000">
    <flipped objectcount="8514" bytes="467600" />
    <tenured objectcount="0" bytes="0" />
    <finalization objectsqueued="1" />
    <scavenger tiltratio="50" />
    <nursery freebytes="463696" totalbytes="1048576" percent="44" tenureage="10" />
    <tenured freebytes="3029168" totalbytes="3145728" percent="96" >
      <soa freebytes="2871984" totalbytes="2988544" percent="96" />
      <loa freebytes="157184" totalbytes="157184" percent="100" />
    </tenured>
    <time totalms="1.962" />
  </gc>
  <nursery freebytes="461648" totalbytes="1048576" percent="44" />
  <tenured freebytes="3029168" totalbytes="3145728" percent="96" >
    <soa freebytes="2871984" totalbytes="2988544" percent="96" />
    <loa freebytes="157184" totalbytes="157184" percent="100" />
  </tenured>
  <refs soft="3" weak="2" phantom="1" dynamicSoftReferenceThreshold="32" maxSoftReferenceThreshold="32" /> <time totalms="2.023" />
</af>

The af type and gc type clearly shows that it is a scavenge type GC.

The <nursery> element appears in three places. The first one shows to size of the new space and the amount of free space available. The second one shows the same metrics right after scavenge. The third one shows the metrics after the new object has been allocated (the object that could not be allocated earlier that resulted in an allocation failure). The sizes of the tenured space should not change before and after a scavenge.

The -Xtgc:excessiveGC option comes handy to detect any GC related performance problem. This will output the following after every GC.

excessiveGC: gcid="6" intimems="7.014" outtimems="284.637"
 percent="2.40" averagepercent="0.40" 

Here, intimems shows the amount of time spent doing the last GC (with GC id of 9). The outtimems parameter shows the interval between the last two GCs (GC id 8 and 9). The percent and averagepercent parameters show the percentage of the time spent doing GC compared to normal execution of the JVM.

By default, verbose GC output goes to native standard error file. The –Xverbosegclog option allows you to route verbose GC output to a different file. For example:

–Xverbosegclog:/tmp/gc.log

Follow Us

Blog Categories