Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Runtime Commited Heap Resizing

DZone's Guide to

Runtime Commited Heap Resizing

· Java Zone
Free Resource

Build vs Buy a Data Quality Solution: Which is Best for You? Gain insights on a hybrid approach. Download white paper now!

New day, new version of Java... nice :)

We used to update minor Java versions mostly due to security issues. But sometimes those minor updates brings us brand new, awesome features. So was for example with 7u40 which brought us awesome Mission Control known from JRockit. (If you are interested in tracking changes across Java updates take a look at
http://www.oracle.com/technetwork/java/javase/8all-relnotes-2226344.html for Java 8 or http://www.java.com/en/download/faq/release_changes.xml for Java 7) 

Same situation is now with versions  7u60 and  8u20. Since now flags  MinHeapFreeRatio and MaxHeapFreeRatio became manageable, which means we can change its values... in runtime :) 


You can always check which flags in JVM are manageable by invoking

java -XX:+PrintFlagsFinal -XX:+UseG1GC -version |grep manageable
intx CMSAbortablePrecleanWaitMillis  = 100  {manageable}
intx CMSWaitDuration  = 2000  {manageable}
bool HeapDumpAfterFullGC  = false  {manageable}
bool HeapDumpBeforeFullGC  = false  {manageable}
bool HeapDumpOnOutOfMemoryError  = false  {manageable}
ccstr HeapDumpPath  =  {manageable}
uintx MaxHeapFreeRatio  = 70  {manageable}
uintx MinHeapFreeRatio  = 40  {manageable}
bool PrintClassHistogram  = false  {manageable}
bool PrintClassHistogramAfterFullGC  = false  {manageable}
bool PrintClassHistogramBeforeFullGC  = false  {manageable}
bool PrintConcurrentLocks  = false  {manageable}
bool PrintGC  = false  {manageable}
bool PrintGCDateStamps  = false  {manageable}
bool PrintGCDetails  = false  {manageable}
bool PrintGCTimeStamps  = false  {manageable}
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
Getting back to our flags. MinHeapFreeRatio defines minimum percentage of heap free after GC to avoid expansion, while  MaxHeapFreeRation (as you can expect) describes maximum percentage of heap free after GC to avoid shrinking. 

Now let's see how this heap resizing works. At first we need to find java process right for testing. I'll going to use running  IntelliJ IDEA.
As you know java pids can be found by invoking  jps command:

jps -l
17136 com.intellij.idea.Main
We already know our testing pid, so it's good time to find out some heap statistics. We'll use  jmapcommand to do that:
jmap -heap 17136
Attaching to process ID 17136, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.20-b23
using thread-local object allocation.
Garbage-First (G1) GC with 4 thread(s)
Heap Configuration:
MinHeapFreeRatio  = 40
MaxHeapFreeRatio  = 70
MaxHeapSize  = 2147483648 (2048.0MB)
NewSize  = 1363144 (1.2999954223632812MB)
MaxNewSize  = 1287651328 (1228.0MB)
OldSize  = 5452592 (5.1999969482421875MB)
NewRatio  = 2
SurvivorRatio  = 8
MetaspaceSize  = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize  = 17592186044415 MB
G1HeapRegionSize  = 1048576 (1.0MB)
Heap Usage:
G1 Heap:
regions  = 2048
capacity = 702545920 (670.0MB)
used  = 284513824 (271.3335266113281MB)
free  = 418032096 (398.6664733886719MB)
40.49754128527285% used
As you can see I'm using  G1 GC with 2GB max heap size (-Xmx2g). Heap usage is about 40%. Now we should run full gc to clean up a little bit before playing.

jcmd 17136 GC.run
Then jmap one more time and we can see 
Heap Configuration:
MinHeapFreeRatio  = 40
MaxHeapFreeRatio  = 70
Heap Usage:
G1 Heap:
regions  = 2048
capacity = 439353344 (419.0MB)
used  = 135954032 (129.65586853027344MB)
free  = 303399312 (289.34413146972656MB)
30.944121367607025% used
Finally we're ready to start resezing. I will change value of  MaxHeapFreeRatio flag by using  jinfotool:

jinfo -flag MaxHeapFreeRatio=50 17136
After that we have to again run full gc to force resizing. And now our heap looks like that: 
Heap Configuration:
MinHeapFreeRatio  = 40
MaxHeapFreeRatio  = 50
Heap Usage:
G1 Heap:
regions  = 2048
capacity = 166723584 (159.0MB)
used  = 82849400 (79.01134490966797MB)
free  = 83874184 (79.98865509033203MB)
49.69266975450816% used
As you can see heap shrank from 419 to 159 MB.

Now we can try going in other way: 

jinfo -flag MaxHeapFreeRatio=90 17136
jinfo -flag MinHeapFreeRatio=85 17136
gives  jmap output 

Heap Configuration:
MinHeapFreeRatio  = 85
MaxHeapFreeRatio  = 90
Heap Usage:
G1 Heap:
regions  = 2048
capacity = 465567744 (444.0MB)
used  = 69816504 (66.58220672607422MB)
free  = 395751240 (377.4177932739258MB)
14.995992505872572% used
Resizing worked one more time and heap capacity has increased from 159MB to 444MB. We described that minimum 85% of our heap capacity should be free, and that pointed JVM to resize the heap to gain at most 15% usage. Now we're waiting for runtime XMX changing ;)

Build vs Buy a Data Quality Solution: Which is Best for You? Maintaining high quality data is essential for operational efficiency, meaningful analytics and good long-term customer relationships. But, when dealing with multiple sources of data, data quality becomes complex, so you need to know when you should build a custom data quality tools effort over canned solutions. Download our whitepaper for more insights into a hybrid approach.

Topics:

Published at DZone with permission of Jakub Kubrynski, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}