Java Heap fragmentation is an interesting problem, which triggers long pausing full garbage collection cycles. In this article we would like to attempt to explain the heap fragmentation.
Let’s say developer write a code ‘new BMW()’. This will create a new BMW object in the heap memory space. Example:
Fig: New object created in JVM Heap
Let’s say now application creates 3 more new objects: ‘Toyota’, ‘Honda’, ‘Tesla’. Now JVM’s heap memory will start to look like this:
Fig: More objects are created in JVM Heap
Let’s say after some time, no other objects are referencing Toyota and Tesla objects, then garbage collector will remove Toyota and Tesla objects from the memory. Thus, after garbage collection cycle now heap memory will start to look like this:
Fig: Garbage collection removes unused objects from JVM Heap
Let’s say now application is creating a new ‘Truck’ object which is bigger in size. Even though there is sufficient space to accommodate Truck object in memory, there isn’t enough contiguous space to store the Truck object in the memory, because heap is fragmented.
Fig: JVM heap is fragmented, there is not enough contiguous space to accommodate ‘Truck’ object
When heap is fragmented like this Full Garbage Collection is triggered. Full GC will start compacting the memory i.e. it move BMW and Honda objects next to each other, so that there is enough contiguous memory. Typically, Full GC which does the compaction ends up pausing JVM for a longer duration.
Note: To study the amount of heap fragmentation and pause times incurred by your application due to Full garbage collection cycles and steps to reduce them you may consider using free garbage collection log analysis tools like GCeasy, Garbage Cat,
Fig: JVM Heap after compaction
After compaction there will be sufficient contiguous memory to store the Truck object into memory. Thus, Truck object can be stored in memory.
Fig: JVM heap able to accommodate ‘Truck’ object after compaction