Practical case JVM tunning to avoid full GC

613 views Asked by At

I have read and read but they only explain Garbage Collection in a theoretically way, I think it must be really complicated to explain how to solve a practical issue.

My configuration

export JAVA_HOME=/usr/java/jdk6
JAVA_OPTS="-Xms272m -Xmx272m -XX:MaxPermSize=272m -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails"

When the server starts, all goes smooth as silk

29.846: [GC 29.846: [DefNew: 74109K->1940K(83520K), 0.0125820 secs] 106982K->34813K(269248K), 0.0126230 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
30.002: [GC 30.002: [DefNew: 76016K->1502K(83520K), 0.0092930 secs] 108889K->34375K(269248K), 0.0093380 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
31.745: [GC 31.745: [DefNew: 75443K->4722K(83520K), 0.0369630 secs] 108316K->37595K(269248K), 0.0370130 secs] [Times: user=0.02 sys=0.00, real=0.04 secs] 
33.122: [GC 33.122: [DefNew: 78962K->6065K(83520K), 0.0444350 secs] 111835K->39481K(269248K), 0.0444850 secs] [Times: user=0.03 sys=0.00, real=0.04 secs] 
34.183: [GC 34.183: [DefNew: 80258K->4880K(83520K), 0.0371350 secs] 113674K->41044K(269248K), 0.0371830 secs] [Times: user=0.03 sys=0.00, real=0.03 secs] 

The amount of memory which is not being collected grows and sometimes some full gc are performed, but the system recovers from these

356.210: [Full GC 356.210: [Tenured: 74012K->66067K(185728K), 0.2215880 secs] 126231K->66067K(269248K), [Perm : 70207K->70207K(70208K)], 0.2216510 secs] [Times: user=0.22 sys=0.00, real=0.22 secs] 

Finally it only performs full gc

61587.386: [Full GC 61587.386: [Tenured: 185728K->185728K(185728K), 0.4045190 secs] 269107K->188117K(269248K), [Perm : 85394K->85394K(85504K)], 0.4045860 secs] [Times: user=0.40 sys=0.00, real=0.41 secs] 
61587.820: [Full GC 61587.820: [Tenured: 185728K->185728K(185728K), 0.4075960 secs] 268851K->187688K(269248K), [Perm : 85394K->85394K(85504K)], 0.4076610 secs] [Times: user=0.40 sys=0.00, real=0.41 secs] 
61588.258: [Full GC 61588.258: [Tenured: 185728K->185727K(185728K), 0.4184530 secs] 269042K->187217K(269248K), [Perm : 85394K->85248K(85504K)], 0.4185420 secs] [Times: user=0.41 sys=0.00, real=0.41 secs] 
61588.702: [Full GC 61588.702: [Tenured: 185727K->185727K(185728K), 0.4054800 secs] 269129K->187216K(269248K), [Perm : 85248K->85248K(85504K)], 0.4055560 secs] [Times: user=0.40 sys=0.00, real=0.41 secs] 
61589.145: [Full GC 61589.145: [Tenured: 185727K->185727K(185728K), 0.4042100 secs] 269048K->187247K(269248K), [Perm : 85248K->85248K(85504K)], 0.4042770 secs] [Times: user=0.40 sys=0.00, real=0.41 secs] 

and exceptions arise

Jun 10, 2015 5:12:24 PM org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: Cannot create a session after the response has been committed

The web application runs with Java 1.6 on Tomcat 7 Server and uses Struts 2 (2.3.24) Any help would be so much appreciated because I am just a java programmer and I didn't know java had these big caveats under the hood. Thanks

2

There are 2 answers

6
AudioBubble On

There is two strategies to prevent full gc:

1) minimize count of long-living objects. Perfectly to zero. If you store link to some object for time that more than young gc interval that object will live in heap until full gc. Usually it's imposible to create java app completely without long-living objects but you can reduce count of it.

Worst situation when your app produce long-living objects and never frees it, it works like memory leak and lead to outofmemory error

2) enlarge heap and young generation size (1st give you more time before gc, second enlarge interval between young gc (less long-lived objects). Prevent full gc by rebooting app (based on heap size for example). Be careful. Big young gen leads to bigger pause on young gc.

modern G1 gc (default in Java 8?) should decrease count of full gc calls

I have experience with app that use 10G young Gen 60G heap at start and max heap size over 200GB. Full gc never called (we reboot it every 2-5 days). Young gc pause 0.1-0.3 seconds every 1-5 minutes.

1
the8472 On

Your problem is much more fundamental than a full GC. You didn't even try to understand what is happening right now, i.e. what current default settings apply, let alone changing the defaults.

Also Full GCs are not necessarily bad in themselves.

-Xmx272m

This is the max heap size. I.e. the maximum amount of heap the application is allowed to use. The guides you linked have several chapters on this topic.

Which part of the guides have you not understood?

DefNew

This is the serial young gen collector. It's singlethreaded (read: slow)

[Times: user=0.41 sys=0.00, real=0.41 secs]

user == real time implies also single-threaded old gen collection.

export JAVA_HOME=/usr/java/jdk6

java 6 has long reached end of life. Update to java 8, it provides new and improved collectors

I have read and read but they only explain Garbage Collection in a theoretically way

The guides you linked explain many available options, not just academic theory. It doesn't seem like you have even experimented with any of the options.

because I am just a java programmer and I didn't know java had these big caveats under the hood.

GC effectively is part of java. As a programmer you need to understand it, because ignoring it will make your application crash or fail to perform properly.

If you think that you do not need to know you are wrong.