错误 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 11:37:02  来源:igfitidea点击:

Error java.lang.OutOfMemoryError: GC overhead limit exceeded

javagarbage-collectionout-of-memoryheap-memory

提问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 OutOfMemoryErroris, 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 Errorso 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 版本,并包含有关此特定问题的部分:

回答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:-UseGCOverheadLimitto 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:

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

  1. Increase the heap size, for example -Xmx1g.
  2. Enable the concurrent low pause collector -XX:+UseConcMarkSweepGC.
  3. Reuse existing objects when possible to save some memory.
  1. 增加堆大小,例如-Xmx1g
  2. 启用并发低暂停收集器-XX:+UseConcMarkSweepGC
  3. 尽可能重用现有对象以节省一些内存。

If necessary, the limit checkcan be disabled by adding the option -XX:-UseGCOverheadLimitto 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

For me, the following steps worked:

对我来说,以下步骤有效:

  1. Open the eclipse.inifile
  2. Change

    -Xms40m
    -Xmx512m
    

    to

    -Xms512m
    -Xmx1024m
    
  3. Restart Eclipse

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

    -Xms40m
    -Xmx512m
    

    -Xms512m
    -Xmx1024m
    
  3. 重启 Eclipse

See here

看这里

回答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.OutOfMemoryErroris thrown. [...]

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

在垃圾回收之后,如果Java 进程花费了大约 98% 以上的时间进行垃圾回收,并且如果它正在回收不到 2% 的堆并且到目前为止一直在执行最后 5 个(编译时间常数)连续垃圾集合,然后java.lang.OutOfMemoryError抛出 a。[...]

  1. Increase the heap sizeif current heap is not enough.
  2. If you still get this error after increasing heap memory, use memory profiling toolslike MAT( Memory analyzer tool), Visual VMetc and fix memory leaks.
  3. 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
  4. Apart from setting heap memory with -Xms1g -Xmx2g, try

    -XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m  
    -XX:ParallelGCThreads=n -XX:ConcGCThreads=n
    
  1. 如果当前堆不够,则增加堆大小
  2. 如果在增加堆内存后仍然出现此错误,请使用内存分析工具,MAT(内存分析器工具)、 Visual VM等并修复内存泄漏。
  3. 将 JDK 版本升级到最新版本 (1.8.x) 或至少 1.7.x 并使用 G1GC 算法。. G1 GC 的吞吐量目标是 90% 的应用程序时间和 10% 的垃圾收集时间
  4. 除了使用 - 设置堆内存之外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.gradlefile

打开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"
    }
}