当我执行我的JUnit
测试时,会遇到这个错误信息:
java.lang.OutOfMemoryError: GC overhead limit exceeded
我知道什么是OutOfMemoryError
,但是GC overhead limit是什么意思?我该如何解决这个问题?
当我执行我的JUnit
测试时,会遇到这个错误信息:
java.lang.OutOfMemoryError: GC overhead limit exceeded
我知道什么是OutOfMemoryError
,但是GC overhead limit是什么意思?我该如何解决这个问题?
这条消息意味着由于某种原因,垃圾收集器花费了过多的时间(默认情况下进程 CPU 时间的 98%),并且每次运行恢复的内存很少(默认情况下堆的 2%)。
这实际上意味着您的程序停止了所有进展,并一直忙于运行垃圾收集。
为了防止应用程序在没有完成任何工作的情况下消耗 CPU 时间,JVM 抛出此 Error
,以便您有机会诊断问题。
我见过这种情况发生的罕见情况是,一些代码正在创建大量临时对象和大量弱引用对象,而已经非常受限制的内存环境中。
查看 Java GC 调优指南,该指南适用于各种 Java 版本,并包含有关此特定问题的部分:
引用 Oracle 文章 "Java SE 6 HotSpot[tm] 虚拟机垃圾回收调优" 中的一段:
过度 GC 时间和 OutOfMemoryError
如果垃圾回收花费的时间超过总时间的 98%,且恢复的堆内存少于 2%,并行收集器将抛出 OutOfMemoryError。这个特性旨在防止由于堆太小,应用程序运行了很长时间但几乎没有进展。如果需要,可以通过在命令行中添加选项
-XX:-UseGCOverheadLimit
来禁用此功能。
编辑:看起来有人打字比我快 :)
List
对象导致 GC 被调用了 39 次,而不是 22 次。 - Mark Stewart通常是代码的问题。这里有一个简单的例子:
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");
}
}
在Windows 7 32位上使用Java 1.6.0_24-b07。
java -Xloggc:gc.log GarbageCollector
然后查看gc.log
当面临只能实现这样的循环或处理现有行为不佳的代码时,尽管这不是最好的测试或最好的设计,但选择重复使用对象而不是创建新对象可以减少垃圾回收器干扰的次数...
gc.log
文件中行数的数量得出的。我的测试显示总体上次数要少得多,但BETTER的“触发”次数最少,而现在BAD比WORST更糟糕。我的计数:BAD:26,WORSE:22,BETTER:21。 - Mark StewartList<Double> list
,而不是在外部循环之前,并触发了39次垃圾回收。 - Mark Stewartjava.lang.OutOfMemoryError
异常。 [...]除了使用 -Xms1g -Xmx2g
设置堆内存外,也可以尝试
-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m
-XX:ParallelGCThreads=n -XX:ConcGCThreads=n
查看更多有关G1GC的相关问题
只需在运行配置的VM参数中设置该选项,稍微增加堆大小即可。
路径为:运行 → 运行配置 → 参数 → VM参数
-Xms1024M -Xmx2048M
Xms - 用于指定最小限制
Xmx - 用于指定最大限制
试一试
打开build.gradle
文件
android {
dexOptions {
javaMaxHeapSize = "4g"
}
}
以下方法适用于我。只需添加以下片段:
android {
compileSdkVersion 25
buildToolsVersion '25.0.1'
defaultConfig {
applicationId "yourpackage"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions {
javaMaxHeapSize "4g"
}
}
dexOptions {
javaMaxHeapSize "1g"
}
添加以下行到gradle中:
dexOptions {
javaMaxHeapSize "4g"
}