错误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:-UseGCOverheadLimit
closures此-XX:-UseGCOverheadLimit
更多信息在这里
编辑:看起来像有人可以input比我快:)
如果您确定程序中没有内存泄漏 ,请尝试:
- 增加堆大小,例如
-Xmx1g
。 - 启用并发低暂停收集器
-XX:+UseConcMarkSweepGC
。 - 尽可能重用现有对象以节省一些内存。
如有必要,可以通过在命令行中添加-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
- 如果当前堆不够, 增加堆大小 。
- 如果增加堆内存后仍然出现此错误,请使用MAT (内存分析工具), Visual VM等内存分析工具并修复内存泄漏。
- 将JDK版本升级到最新版本(1.8.x)或至less1.7.x并使用G1GCalgorithm。 。 G1 GC的吞吐量目标是90%的应用程序时间和10%的垃圾收集时间
-
除了使用
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技术文章
对我来说,以下步骤起作用:
- 打开
eclipse.ini
文件 -
更改
-Xms40m -Xmx512m
至
-Xms512m -Xmx1024m
-
重新启动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”。 它可以解决堆大小的问题。