错误java.lang.OutOfMemoryError:超出GC开销限制

我执行我的JUnittesting时遇到此错误消息:

java.lang.OutOfMemoryError: GC overhead limit exceeded 

我知道什么是OutOfMemoryError ,但GC开销限制是什么意思? 我该如何解决这个问题?

这个消息意味着由于某种原因,垃圾收集器需要花费过多的时间(默认是进程的所有CPU时间的98%),并且在每次运行中恢复很less的内存(默认为堆的2%)。

这实际上意味着您的程序停止任何进度,并且正在忙于只运行垃圾回收。

为了防止应用程序在没有完成任何事情的情况下吸收CPU时间,JVM会抛出此Error以便您有机会诊断问题。

在我看到这种情况发生的罕见情况下,一些代码在已经非常内存有限的环境中创build了大量的临时对象和大量的弱引用对象。

看看这篇文章的细节(特别是这个部分 )。

如果在垃圾收集中花费太多的时间太less,GC会抛出这个exception。 CPU占用CPU的时间为98%,恢复的堆less于2%。

此function旨在防止应用程序长时间运行,而由于堆太小,进行很less或没有进度。

您可以使用命令行选项-XX:-UseGCOverheadLimitclosures此-XX:-UseGCOverheadLimit

更多信息在这里

编辑:看起来像有人可以input比我快:)

如果您确定程序中没有内存泄漏 ,请尝试:

  1. 增加堆大小,例如-Xmx1g
  2. 启用并发低暂停收集器-XX:+UseConcMarkSweepGC
  3. 尽可能重用现有对象以节省一些内存。

如有必要,可以通过在命令行中添加-XX:-UseGCOverheadLimit选项来禁用限制检查 。

这通常是代码。 这是一个简单的例子:

 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"); } } 

使用java 1.6.0_24-b07在Windows7 32位上。

java -Xloggc:gc.log GarbageCollector

然后看看gc.log

  • 用BAD方法触发444次
  • 使用WORSE方法触发666次
  • 使用BETTER方法触发354次

现在被授予,这不是最好的testing或最好的devise,但是当面对一个你没有select,但实现这样一个循环的情况,或者在处理现有的代码行为不好的情况下,select重用对象而不是创build新的可以减less垃圾收集器获取的次数…

通过设置这个选项来增加堆的大小

运行→运行configuration→参数→VM参数

 -Xms1024M -Xmx2048M 

Xms – 用于最小限制

Xmx – 用于最大限制

导致错误

超出GC开销限制“表示垃圾收集器一直在运行,Java程序进度非常缓慢。

在垃圾收集之后,如果Java进程花费了大约98%的时间进行垃圾收集,并且如果它正在恢复小于2%的堆,并且一直在执行最后5个(编译时间常量)连续垃圾集合,然后抛出一个java.lang.OutOfMemoryError

  1. 如果当前堆不够, 增加堆大小
  2. 如果增加堆内存后仍然出现此错误,请使用MAT (内存分析工具), Visual VM等内存分析工具并修复内存泄漏。
  3. 将JDK版本升级到最新版本(1.8.x)或至less1.7.x并使用G1GCalgorithm。 。 G1 GC的吞吐量目标是90%的应用程序时间和10%的垃圾收集时间
  4. 除了使用Xms1g -Xmx2g设置堆内存Xms1g -Xmx2g ,请尝试

     -XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m -XX:ParallelGCThreads=n -XX:ConcGCThreads=n 

看看有关G1GC的更多相关问题

Java 7(JDK 7)垃圾收集和文档上的G1

生产中的Java G1垃圾收集

用于GC微调的Oracle技术文章

对我来说,以下步骤起作用:

  1. 打开eclipse.ini文件
  2. 更改

     -Xms40m -Xmx512m 

     -Xms512m -Xmx1024m 
  3. 重新启动Eclipse

看这里

以下为我工作。 只需添加下面的代码片段:

 android { compileSdkVersion 25 buildToolsVersion '25.0.1' defaultConfig { applicationId "yourpackage" minSdkVersion 10 targetSdkVersion 25 versionCode 1 versionName "1.0" multiDexEnabled true } dexOptions { javaMaxHeapSize "4g" } } 

尝试这个

打开build.gradle文件

  android { dexOptions { javaMaxHeapSize = "4g" } } 

在你的build.gradle(Module:app)文件中增加javaMaxHeapsize

 dexOptions { javaMaxHeapSize "1g" } 

到(在gradle中添加此行)

  dexOptions { javaMaxHeapSize "4g" } 

您需要增加Jdeveloper中的内存大小,然后转到setDomainEnv.cmd

 set WLS_HOME=%WL_HOME%\server set XMS_SUN_64BIT=**256** set XMS_SUN_32BIT=**256** set XMX_SUN_64BIT=**3072** set XMX_SUN_32BIT=**3072** set XMS_JROCKIT_64BIT=**256** set XMS_JROCKIT_32BIT=**256** set XMX_JROCKIT_64BIT=**1024** set XMX_JROCKIT_32BIT=**1024** if "%JAVA_VENDOR%"=="Sun" ( set WLS_MEM_ARGS_64BIT=**-Xms256m -Xmx512m** set WLS_MEM_ARGS_32BIT=**-Xms256m -Xmx512m** ) else ( set WLS_MEM_ARGS_64BIT=**-Xms512m -Xmx512m** set WLS_MEM_ARGS_32BIT=**-Xms512m -Xmx512m** ) 

 set MEM_PERM_SIZE_64BIT=-XX:PermSize=**256m** set MEM_PERM_SIZE_32BIT=-XX:PermSize=**256m** if "%JAVA_USE_64BIT%"=="true" ( set MEM_PERM_SIZE=%MEM_PERM_SIZE_64BIT% ) else ( set MEM_PERM_SIZE=%MEM_PERM_SIZE_32BIT% ) set MEM_MAX_PERM_SIZE_64BIT=-XX:MaxPermSize=**1024m** set MEM_MAX_PERM_SIZE_32BIT=-XX:MaxPermSize=**1024m** 

在NetBeans中,devise最大堆大小可能会有帮助。 进入“运行”,进入“设置项目configuration”,在popup窗口的“运行”中select“自定义”,进入“虚拟机选项”,填写“-Xms2048m -Xmx2048m”。 它可以解决堆大小的问题。