What means the error-message 'java.lang.OutOfMemoryError: GC overhead limit exceeded' in Java?

转国内的:

一、异常如下:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded

二、解释:
JDK6新增错误类型。当GC为释放很小空间占用大量时间时抛出。
一般是因为堆太小。导致异常的原因:没有足够的内存。

三、解决方案:

1、查看系统是否有使用大内存的代码或死循环。
2、可以添加JVM的启动参数来限制使用内存:-XX:-UseGCOverheadLimit

 

 

This message means that for some reason the garbage collector is taking an excessive amount of time (by default 98% of all CPU time of the process) and recovers very little memory in each run (by default 2% of the heap).

This effectively means that your program stops doing any progress and is busy running only the garbage collection at all time.

To prevent your application from soaking up CPU time without getting anything done, the JVM throws this Error so that you have a chance of diagnosing the problem.

The rare cases where I've seen this happen is where some code was creating tons of temporary objects and tons of weakly-referenced objects in an already very memory-constrained environment.

Check out this article for details (specifically this part).

 

 

The GC throws this exception when too much time is spent in garbage collection for too little return, eg. 98% of CPU time is spent on GC and less than 2% of heap is recovered.

This feature is designed to prevent applications from running for an extended period of time while making little or no progress because the heap is too small.

You can turn this off with the command line option -XX:-UseGCOverheadLimit

More info here

 

 

It's usually the code. Here's a simple example:

import java.util.*; 
 
public class GarbageCollector { 
 
   
public static void main(String... args) { 
 
       
System.out.printf("Testing...%n"); 
       
List<Double> list = new ArrayList<Double>(); 
       
for (int outer = 0; outer < 10000; outer++) { 
 
           
// list = new ArrayList<Double>(10000); // BAD 
           
// list = new ArrayList<Double>(); // WORSE 
            list
.clear(); // BETTER 
 
           
for (int inner = 0; inner < 10000; inner++) { 
                list
.add(Math.random()); 
           
} 
 
           
if (outer % 1000 == 0) { 
               
System.out.printf("Outer loop at %d%n", outer); 
           
} 
 
       
} 
       
System.out.printf("Done.%n"); 
   
} 
} 

Using java 1.6.0_24-b07 On a Windows7 32 bit.

java -Xloggc:gc.log GarbageCollector

Then look at gc.log

  • Triggered 444 times using BAD method
  • Triggered 666 times using WORSE method
  • Triggered 354 times using BETTER method

Now granted, this is not the best test or the best design but when faced with a situation where you have no choice but implementing such a loop or when dealing with existing code that behaves badly, choosing to reuse objects instead of creating new ones can reduce the number of times the garbage collector gets in the way...

posted @ 2011-05-23 17:10  规格严格-功夫到家  阅读(672)  评论(0编辑  收藏  举报