错误 java.lang.OutOfMemoryError:超出 GC 开销限制
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1393486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Error java.lang.OutOfMemoryError: GC overhead limit exceeded
提问by Mnementh
I get this error message as I execute my JUnit tests:
我在执行 JUnit 测试时收到此错误消息:
java.lang.OutOfMemoryError: GC overhead limit exceeded
I know what an OutOfMemoryError
is, but what does GC overhead limit mean? How can I solve this?
我知道 anOutOfMemoryError
是什么,但是 GC 开销限制是什么意思?我该如何解决这个问题?
采纳答案by Joachim Sauer
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).
此消息意味着由于某种原因垃圾收集器占用了过多的时间(默认为进程所有 CPU 时间的 98%)并且在每次运行中回收的内存非常少(默认为堆的 2%)。
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.
为了防止您的应用程序在没有完成任何事情的情况下占用 CPU 时间,JVM 会抛出此问题,Error
以便您有机会诊断问题。
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 the Java GC tuning guide, which is available for various Java versions and contains sections about this specific problem:
查看 Java GC 调优指南,该指南适用于各种 Java 版本,并包含有关此特定问题的部分:
- Java 11 tuning guidehas dedicated sections on excessive GC for different garbage collectors:
- for the Parallel Collector
- for the Concurrent Mark Sweep (CMS) Collector
- there is no mention of this specific error condition for the Garbage First (G1) collector.
- Java 8 tuning guideand its Excessive GC section
- Java 6 tuning guideand its Excessive GC section.
- Java 11 调优指南有专门的部分介绍不同垃圾收集器的过度 GC:
- 对于并行收集器
- 用于并发标记扫描 (CMS) 收集器
- 没有提及垃圾优先 (G1) 收集器的这种特定错误条件。
- Java 8 调优指南及其过度 GC 部分
- Java 6 调优指南及其Excessive GC 部分。
回答by dave
Quoting from Oracle's article "Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning":
引用 Oracle 的文章“Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning”:
Excessive GC Time and OutOfMemoryError
The parallel collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown. 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. If necessary, this feature can be disabled by adding the option
-XX:-UseGCOverheadLimit
to the command line.
GC 时间过长和 OutOfMemoryError
如果垃圾收集花费了太多时间,并行收集器将抛出 OutOfMemoryError:如果超过 98% 的总时间花费在垃圾收集上,而回收的堆不到 2%,则会抛出 OutOfMemoryError。此功能旨在防止应用程序长时间运行而由于堆太小而进展甚微或没有进展。如有必要,可以通过将选项添加
-XX:-UseGCOverheadLimit
到命令行来禁用此功能。
EDIT: looks like someone can type faster than me :)
编辑:看起来有人可以比我打字更快:)
回答by Mike
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 Windows 7 32 bit.
在 Windows 7 32 位上使用 Java 1.6.0_24-b07。
java -Xloggc:gc.log GarbageCollector
Then look at gc.log
然后看看 gc.log
- Triggered 444 times using BAD method
- Triggered 666 times using WORSE method
- Triggered 354 times using BETTER method
- 使用 BAD 方法触发 444 次
- 使用 WORSE 方法触发 666 次
- 使用 BETTER 方法触发 354 次
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...
现在承认,这不是最好的测试或最好的设计,但是当面临这样的情况时,您别无选择,只能实现这样的循环,或者在处理表现不佳的现有代码时,选择重用对象而不是创建新对象可以减少垃圾收集器妨碍的次数...
回答by Vitalii Fedorenko
If you are sure there are no memory leaksin your program, try to:
如果您确定程序中没有内存泄漏,请尝试:
- Increase the heap size, for example
-Xmx1g
. - Enable the concurrent low pause collector
-XX:+UseConcMarkSweepGC
. - Reuse existing objects when possible to save some memory.
- 增加堆大小,例如
-Xmx1g
。 - 启用并发低暂停收集器
-XX:+UseConcMarkSweepGC
。 - 尽可能重用现有对象以节省一些内存。
If necessary, the limit checkcan be disabled by adding the option -XX:-UseGCOverheadLimit
to the command line.
如有必要,可以通过将选项添加到命令行来禁用限制检查-XX:-UseGCOverheadLimit
。
回答by chopss
Just increase the heap size a little by setting this option in
只需通过设置此选项来稍微增加堆大小
Run → Run Configurations → Arguments → VM arguments
运行 → 运行配置 → 参数 → VM 参数
-Xms1024M -Xmx2048M
Xms- for minimum limit
Xms- 用于最小限制
Xmx- for maximum limit
Xmx- 最大限制
回答by Sunil Kumar Sahoo
回答by Ravindra babu
Cause for the error according to the Java [8] Platform, Standard Edition Troubleshooting Guide: (emphasis and line breaks added)
根据Java [8] Platform, Standard Edition 故障排除指南的错误原因:(添加了强调和换行符)
[...] "GC overhead limit exceeded" indicates that the garbage collector is running all the time and Java program is making very slow progress.
After a garbage collection, if the Java process is spending more than approximately 98% of its time doing garbage collectionand if it is recovering less than 2% of the heap and has been doing so far the last 5 (compile time constant) consecutive garbage collections, then a
java.lang.OutOfMemoryError
is thrown. [...]
[...]“超出GC开销限制”表示垃圾收集器一直在运行,Java程序进展非常缓慢。
在垃圾回收之后,如果Java 进程花费了大约 98% 以上的时间进行垃圾回收,并且如果它正在回收不到 2% 的堆并且到目前为止一直在执行最后 5 个(编译时间常数)连续垃圾集合,然后
java.lang.OutOfMemoryError
抛出 a。[...]
- Increase the heap sizeif current heap is not enough.
- If you still get this error after increasing heap memory, use memory profiling toolslike MAT( Memory analyzer tool), Visual VMetc and fix memory leaks.
- Upgrade JDK version to latest version ( 1.8.x) or at least 1.7.x and use G1GC algorithm. . The throughput goal for the G1 GC is 90 percent application time and 10 percent garbage collection time
Apart from setting heap memory with -
Xms1g -Xmx2g
, try-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m -XX:ParallelGCThreads=n -XX:ConcGCThreads=n
- 如果当前堆不够,则增加堆大小。
- 如果在增加堆内存后仍然出现此错误,请使用内存分析工具,如MAT(内存分析器工具)、 Visual VM等并修复内存泄漏。
- 将 JDK 版本升级到最新版本 (1.8.x) 或至少 1.7.x 并使用 G1GC 算法。. G1 GC 的吞吐量目标是 90% 的应用程序时间和 10% 的垃圾收集时间
除了使用 - 设置堆内存之外
Xms1g -Xmx2g
,还可以尝试-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m -XX:ParallelGCThreads=n -XX:ConcGCThreads=n
Have a look at some more related questions regarding G1GC
看看一些关于 G1GC 的更多相关问题
回答by shashi
You need to increase the memory size in Jdeveloper go to setDomainEnv.cmd.
您需要在 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**
)
and
和
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**
回答by alicanozkara
try this
尝试这个
open the build.gradle
file
打开build.gradle
文件
android {
dexOptions {
javaMaxHeapSize = "4g"
}
}
回答by H.S.H
The following worked for me. Just add the following snippet:
以下对我有用。只需添加以下代码段:
android {
compileSdkVersion 25
buildToolsVersion '25.0.1'
defaultConfig {
applicationId "yourpackage"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions {
javaMaxHeapSize "4g"
}
}