Exploring JVM: Garbage Collection

14 May 2017


(HotSpot) JVM Structure

  1. The performance depends on different JVM structure. As HotSpot is the default JVM for JDK, we mainly talk about it on HotSpot JVM.
  2. The following figure shows the 5 major key components in HotSpot JVM: method area, heap, java threads, program counter registers and native internal threads. And the major components to tune for performance improvement are marked in purple.

Structure of HotSpot JVM.[2]

Basic GC Algorithm

  1. Mark-Delete: The GC algo will start from root and mark each reachable object, then delete all the objects not marked. One thing to note is that we may need to ‘stop the world’ before mark-delete, in case that some new instances created are not marked and get wrongly deleted.
  2. Mark-Compact: Different from the normal mark-delete algo, after deletion, the algo compact all object left. This is to avoid memory fragmentation and better use memory.
  3. Mark-Copy: After marking, the algo copy instance into new space, and change all the pointers of running objects to new space. This algo has shorter pause time compared with the previous two, while using continuous memory space. But in naive implementation, where the old space and new space are the same, 100% additional space is needed. Also, when the surviving rate is high, the efficiency is low.
  4. Modified mark-copy: Basically there are 2 sub-generations in mark-copy. If we have 3 sub-generations, where the first gets 80% of space, 10% for both second and third, then the memory efficiency is much higher. Reason for this is the survivor rate for new generation is much lower than older ones, thus for instance there are only small amount of objects get survived and promoted to older generation.

Illustration of modified mark-copy.[2]

  1. Aging: When an object survives after each GC, its age is incremented by 1. The object is initially in young generation. After certain age, it gets promoted to old generation (tenured). Data in permanent generation include some class and methods, and it is only GC in full GC (normally the last one).

Generation GC

  1. Based on the characteristics of different generation, differnt GC algos are used. In young generation, the survivor rate is low, thus we can use modified mark-copy. In old generation, mark-compact is used instead.
  2. Client and Server Mode. By default the JVM uses client mode, where application starts faster; server mode will make some optimization on application, like making the execution code ‘native’ to run faster.
  3. In young generation, there are mainly Serial, ParNew and Parallel Scavenge modes. As can be told from their names, serial uses single processor, while parallel uses multi-processor. Parallel is generally faster, but it involves concurrency between processors, which may lower its speed. Parallel Scavenge differs from the ParNew in that we can tune more factors like the max pause time (-XX:MaxGCPauseMillis=<N>) and throughput (-XX:GCTimeRatio=<N>).
  4. In old generation, there are Serial Old, Concurrent Mark Sweep (CMS) and Parallel Old. CMS uses mark-delete to decrease pause time, and GC with application thread concurrently (so no ‘stop-the-world’). The drawback is memory inefficiency, which may cause ‘concurrent mode failure’, in which case the JVM will launch GC again and use Serial Old instead (and causes more pause time). CMS is the default mode of server mode old generation GC.
  5. To solve ‘concurrent mode failure’, one solution is to assign more heap space, the other is by tuning -XX:CMSInitiatingOccupancyFraction=<N> , which controls the portion of memory usage (N%) to trigger GC.

References

  1. Java内存管理 by 左潇龙
  2. Java Garbage Collection Basics
comments powered by Disqus