The best way to tune in Java, needs to follow the Thumb Rule.
Thumb Rule: Try to maximize objects reclaimed in young men and Minimize Full GC frequency.
Thumb Rule: Try to maximize objects reclaimed in young men and Minimize Full GC frequency.
-Xms
and –Xmx
options.-server
option is included.StringBuilder
or StringBuffer
a way of life instead of String
.String
as little as possible and process logs as well as we can, a huge
temporary memory is used for parsing XML or JSON, some 10-100 MB.
However, it is difficult not to use XML and JSON. Just understand that
it takes too much memory.OutOfMemoryError
may occur or the number of Full GCs may increase.Classification | Option | Description |
Heap area size | -Xms | Heap area size when starting JVM |
-Xmx | Maximum heap area size | |
New area size | -XX:NewRatio | Ratio of New area and Old area |
-XX:NewSize | New area size | |
-XX:SurvivorRatio | Ratio of Eden area and Survivor area |
-Xms
, -Xmx
, and -XX:NewRatio
options for GC tuning. -Xms
and -Xmx
option are particularly required. How you set the NewRatio
option makes a significant difference on GC performance.-XX:PermSize
and -XX:MaxPermSize
options but only when OutOfMemoryError
occurs and the cause is the Perm area size.Classification | Option | Remarks |
Serial GC | -XX:+UseSerialGC | |
Parallel GC | -XX:+UseParallelGC -XX:ParallelGCThreads=value |
|
Parallel Compacting GC | -XX:+UseParallelOldGC | |
CMS GC | -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=value -XX:+UseCMSInitiatingOccupancyOnly |
|
G1 | -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC |
In JDK 6, these two options must be used together. |
OutOfMemoryError
occurs, you should execute heap dump to verify and remove the cause.Note:
Heap dump is a file of the memory that is used to check the objects and data in the Java memory. This file can be created by using the jmap command included in the JDK. While creating the file, the Java process stops. Therefore, do not create this file while the system is operating.
Search on the Internet the detailed description on heap dump. For Korean readers, see my book I published last year: The story of troubleshooting for Java developers and system operators (Sangmin Lee, Hanbit Media, 2011, 416 pages).
1
2
3
4
| $ jstat -gcutil 21719 1s S0 S1 E O P YGC YGCT FGC FGCT GCT 48.66 0.00 48.10 49.70 77.45 3428 172.623 3 59.050 231.673 48.66 0.00 48.10 49.70 77.45 3428 172.623 3 59.050 231.673 |
–verbosegc
option. For a detailed description on how to generate and tools to analyze logs, I have explained it the previous article. HPJMeter is my favorite among tools that are used to analyze the -verbosegc
log. It is easy to use and analyze. With HPJmeter you can easily check
the distribution of GC execution times and the frequency of GC
occurrence.–gccapacity
option in the stat command to check how much the area is occupied.-verbosegc
option, and then analyze the result.–Xms500m
and –Xmx500m
options. Based on the current status before GC tuning, check the memory
size left after Full GC. If there is about 300 MB left after Full GC,
it is good to set the memory to 1 GB (300 MB (for default usage) + 500
MB (minimum for the Old area) + 200 MB (for free memory)). That means
you should set the memory space with more than 500 MB for the Old area.
Therefore, if you have three operation servers, set one server to 1 GB,
one to 1.5 GB, and one to 2 GB, and then check the result.NewRatio
. NewRatio
is the ratio of the New area and the Old area. If XX:NewRatio=1
, New area:Old area is 1:1. For 1 GB, New area:Old area is 500MB: 500MB. If NewRatio
is 2, New area:Old area is 1:2. Therefore, as the value gets larger,
the Old area size gets larger and the New area size gets smaller.NewRatio
value
significantly affects the entire GC performance. If the New area size is
small, much memory is passed to the Old area, causing frequent Full GC
and taking a long time to handle it.NewRatio 1
would be the best; however, it may not be so. When NewRatio
is set to 2 or 3, the entire GC status may be better. And I have seen such cases.-verbosegc
option, check whether the logs are accumulated as desired with the tail
command. If the option is not exactly set and no log is accumulated,
you will waste your time. If logs are accumulated as desired, check the
result after collecting data for one or two days. The easiest way is to
move logs to the local PC and analyze the data by using HPJMeter.OutOfMemoryError
may occur if you try to complete GC tuning all at once.jstat –gcutil
.
1
2
| S0 S1 E O P YGC YGCT FGC FGCT GCT 12.16 0.00 5.18 63.78 20.32 54 2.047 5 6.946 8.993 |
GC Type | GC Execution Times | GC Execution Time | Average |
Minor GC | 54 | 2.047 | 37 s |
Full GC | 5 | 6.946 | 1,389 ms |
jstat –gccapacity
option to check the memory usage. The result checked from this server is as follows.
1
2
| NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC 212992.0
212992.0 212992.0 21248.0 21248.0 170496.0 1884160.0 1884160.0
1884160.0 1884160.0 262144.0 262144.0 262144.0 262144.0 54 5 |
-verbosegc
log has been added and three options were set for the three instances as shown below. No other option has been added.NewRatio
has been set.NewRatio
. So, how can we determine the best value? To get it, analyze the average response time of Minor GC for each NewRatio
.jstat –gcutil
some days after the JVM of the service had started.
1
2
| S0 S1 E O P YGC YGCT FGC FGCT GCT 8.61 0.00 30.67 24.62 22.38 2424 30.219 0 0.000 30.219 |
-verbosegc
option and the result is as follows.–Xms1g
and –Xmx4g
and the memory allocated was 4 GB.NewRatio
to 3. The result of jstat –gcutil
after a few hours is as follows.
1
2
| S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 30.48 3.31 26.54 37.01 226 11.131 4 11.758 22.890 |
-XX:+UseParallelGC -Xms1536m -Xmx1536m -XX:NewRatio=2
-XX:+UseParallelGC -Xms1536m -Xmx1536m -XX:NewRatio=3
-XX:+UseParallelGC -Xms1g -Xmx1g -XX:NewRatio=3
-XX:+UseParallelOldGC -Xms1536m -Xmx1536m -XX:NewRatio=2
-XX:+UseParallelOldGC -Xms1536m -Xmx1536m -XX:NewRatio=3
-XX:+UseParallelOldGC -Xms1g -Xmx1g -XX:NewRatio=3
OutOfMemoryError
at night each day. It is difficult to detail the reason here, but in
short, batch data processing made a lack of JVM memory. The related
problems are being cleared now.
1
2
3
4
5
6
7
8
| $> jstat –gc $<vmid$> 1000 S0C
S1C S0U S1U EC EU OC OU
PC PU YGC YGCT FGC FGCT GCT 3008.0
3072.0 0.0 1511.1 343360.0 46383.0 699072.0 283690.2
75392.0 41064.3 2540 18.454 4 1.133 19.588 3008.0
3072.0 0.0 1511.1 343360.0 47530.9 699072.0 283690.2
75392.0 41064.3 2540 18.454 4 1.133 19.588 3008.0
3072.0 0.0 1511.1 343360.0 47793.0 699072.0 283690.2
75392.0 41064.3 2540 18.454 4 1.133 19.588 $> |
Option Name | Description |
gc | It shows the current size for each heap area and its current usage (Ede, survivor, old, etc.), total number of GC performed, and the accumulated time for GC operations. |
gccapactiy | It shows the minimum size (ms) and maximum size (mx) of each heap area, current size, and the number of GC performed for each area. (Does not show current usage and accumulated time for GC operations.) |
gccause | It shows the "information provided by -gcutil" + reason for the last GC and the reason for the current GC. |
gcnew | Shows the GC performance data for the new area. |
gcnewcapacity | Shows statistics for the size of new area. |
gcold | Shows the GC performance data for the old area. |
gcoldcapacity | Shows statistics for the size of old area. |
gcpermcapacity | Shows statistics for the permanent area. |
gcutil | Shows the usage for each heap area in percentage. Also shows the total number of GC performed and the accumulated time for GC operations. |
1
2
3
4
| S0C S1C … GCT 1248.0 896.0 … 1.246 1248.0 896.0 … 1.246 … … … … |
Column | Description | Jstat Option |
S0C | Displays the current size of Survivor0 area in KB | -gc -gccapacity -gcnew -gcnewcapacity |
S1C | Displays the current size of Survivor1 area in KB | -gc -gccapacity -gcnew -gcnewcapacity |
S0U | Displays the current usage of Survivor0 area in KB | -gc -gcnew |
S1U | Displays the current usage of Survivor1 area in KB | -gc -gcnew |
EC | Displays the current size of Eden area in KB | -gc -gccapacity -gcnew -gcnewcapacity |
EU | Displays the current usage of Eden area in KB | -gc -gcnew |
OC | Displays the current size of old area in KB | -gc -gccapacity -gcold -gcoldcapacity |
OU | Displays the current usage of old area in KB | -gc -gcold |
PC | Displays the current size of permanent area in KB | -gc -gccapacity -gcold -gcoldcapacity -gcpermcapacity |
PU | Displays the current usage of permanent area in KB | -gc -gcold |
YGC | The number of GC event occurred in young area | -gc -gccapacity -gcnew -gcnewcapacity -gcold -gcoldcapacity -gcpermcapacity -gcutil -gccause |
YGCT | The accumulated time for GC operations for Yong area | -gc -gcnew -gcutil -gccause |
FGC | The number of full GC event occurred | -gc -gccapacity -gcnew -gcnewcapacity -gcold -gcoldcapacity -gcpermcapacity -gcutil -gccause |
FGCT | The accumulated time for full GC operations | -gc -gcold -gcoldcapacity -gcpermcapacity -gcutil -gccause |
GCT | The total accumulated time for GC operations | -gc -gcold -gcoldcapacity -gcpermcapacity -gcutil -gccause |
NGCMN | The minimum size of new area in KB | -gccapacity -gcnewcapacity |
NGCMX | The maximum size of max area in KB | -gccapacity -gcnewcapacity |
NGC | The current size of new area in KB | -gccapacity -gcnewcapacity |
OGCMN | The minimum size of old area in KB | -gccapacity -gcoldcapacity |
OGCMX | The maximum size of old area in KB | -gccapacity -gcoldcapacity |
OGC | The current size of old area in KB | -gccapacity -gcoldcapacity |
PGCMN | The minimum size of permanent area in KB | -gccapacity -gcpermcapacity |
PGCMX | The maximum size of permanent area in KB | -gccapacity -gcpermcapacity |
PGC | The current size of permanent generation area in KB | -gccapacity -gcpermcapacity |
PC | The current size of permanent area in KB | -gccapacity -gcpermcapacity |
PU | The current usage of permanent area in KB | -gc -gcold |
LGCC | The cause for the last GC occurrence | -gccause |
GCC | The cause for the current GC occurrence | -gccause |
TT | Tenuring threshold. If copied this amount of times in young area (S0 ->S1, S1->S0), they are then moved to old area. | -gcnew |
MTT | Maximum Tenuring threshold. If copied this amount of times inside young arae, then they are moved to old area. | -gcnew |
DSS | Adequate size of survivor in KB | -gcnew |
1
2
3
4
| S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 66.44 54.12 10.58 86.63 217 0.928 2 0.067 0.995 0.00 66.44 54.12 10.58 86.63 217 0.928 2 0.067 0.995 0.00 66.44 54.12 10.58 86.63 217 0.928 2 0.067 0.995 |
jstat | -verbosegc | |
Monitoring Target | Java application running on a machine that can log in to a terminal, or a remote Java application that can connect to the network by using jstatd | Only when -verbogc was specified as a JVM starting option |
Output information | Heap status (usage, maximum size, number of times for GC/time, etc.) | Size of ew and old area before/after GC, and GC operation time |
Output Time | Every designated time | Whenever GC occurs |
Whenever useful | When trying to observe the changes of the size of heap area | When trying to see the effect of a single GC |
[GC
[<collector>: <starting occupancy1> -> <ending
occupancy1>, <pause time1> secs] <starting occupancy3>
-> <ending occupancy3>, <pause time3> secs] |
Collector | Name of Collector Used for minor gc |
starting occupancy1 | The size of young area before GC |
ending occupancy1 | The size of young area after GC |
pause time1 | The time when the Java application stopped running for minor GC |
starting occupancy3 | The total size of heap area before GC |
ending occupancy3 | The total size of heap area after GC |
pause time3 | The time when the Java application stopped running for overall heap GC, including major GC |
1
2
3
4
| S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 66.44 54.12 10.58 86.63 217 0.928 2 0.067 0.995 0.00 66.44 54.12 10.58 86.63 217 0.928 2 0.067 0.995 0.00 66.44 54.12 10.58 86.63 217 0.928 2 0.067 0.995 |
1
| [Full
GC [Tenured: 3485K->4095K(4096K), 0.1745373 secs]
61244K->7418K(63104K), [Perm : 10756K->10756K(12288K)], 0.1762129
secs] [Times: user=0.19 sys=0.00, real=0.19 secs] |
What if an object in the old generation need to reference an object in the young generation?To handle these cases, there is something called the a "card table" in the old generation, which is a 512 byte chunk. Whenever an object in the old generation references an object in the young generation, it is recorded in this table. When a GC is executed for the young generation, only this card table is searched to determine whether or not it is subject for GC, instead of checking the reference of all the objects in the old generation. This card table is managed with write barrier. This write barrier is a device that allows a faster performance for minor GC. Though a bit of overhead occurs because of this, the overall GC time is reduced.