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

问题描述 投票:706回答:15

我在执行JUnit测试时收到此错误消息:

java.lang.OutOfMemoryError: GC overhead limit exceeded

我知道OutOfMemoryError是什么,但GC开销限制意味着什么?我怎么解决这个问题?

java garbage-collection out-of-memory heap-memory
15个回答
697
投票

此消息表示由于某种原因,垃圾收集器花费了过多的时间(默认情况下为进程的所有CPU时间的98%),并且在每次运行中恢复的内存非常少(默认情况下为堆的2%)。

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

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

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

查看this article了解详情(特别是this part)。


5
投票

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

dexOptions {
    javaMaxHeapSize "1g"
}

to(在gradle中添加此行)

 dexOptions {
        javaMaxHeapSize "4g"
    }

2
投票

重新启动我的MacBook为我解决了这个问题。


0
投票

您需要在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**

0
投票

我在Android Studio中工作,在尝试生成已签名的APK以供发布时遇到此错误。我能够毫无问题地构建和测试调试APK,但是一旦我想构建一个版本APK,构建过程就会运行几分钟,然后最终以“错误java.lang.OutOfMemoryError:GC终止”超出限额“。我增加了VM和Android DEX编译器的堆大小,但问题仍然存在。最后,经过几个小时和一大杯咖啡后发现问题出现在我的app级“build.gradle”文件中 - 我将发布版本类型的'minifyEnabled'参数设置为'false',从而运行了Proguard的东西代码没有通过代码缩小的过程(参见https://developer.android.com/studio/build/shrink-code.html)。我将'minifyEnabled'参数更改为'true',并且发布版本像梦一样执行:)

简而言之,我必须从以下位置更改我的应用级“build.gradle”文件:// ...

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.sign_config_release
    }
    debug {
        debuggable true
        signingConfig signingConfigs.sign_config_debug
    }
}

//...

    //...

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.sign_config_release
    }
    debug {
        debuggable true
        signingConfig signingConfigs.sign_config_debug
    }
}

//...

0
投票

要在IntelliJ IDEA中增加堆大小,请遵循以下说明。它对我有用。

对于Windows用户,

转到安装IDE的位置并搜索以下内容。

idea64.exe.vmoptions

编辑文件并添加以下内容。

-Xms512m
-Xmx2024m
-XX:MaxPermSize=700m
-XX:ReservedCodeCacheSize=480m

这就对了 !!


-1
投票

在Netbeans中,设计最大堆大小可能会有所帮助。转到Run => Set Project Configuration => Customize。在Run of the popped up窗口中,转到VM Option,填写-Xms2048m -Xmx2048m。它可以解决堆大小问题。


195
投票

当垃圾收集花费太多时间以获得太少的回报时,GC会抛出此异常,例如。在GC上花费了98%的CPU时间,并且恢复了不到2%的堆。

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

您可以使用命令行选项-XX:-UseGCOverheadLimit将其关闭

更多信息here

编辑:看起来有人可以比我更快打字:)


81
投票

如果您确定程序中没有memory leaks,请尝试:

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

如有必要,可以通过在命令行中添加选项limit check来禁用-XX:-UseGCOverheadLimit


40
投票

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

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在Windows 7 32位上。

java -Xloggc:gc.log GarbageCollector

然后看看gc.log

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

现在被授予,这不是最好的测试或最好的设计,但是当遇到除了实现这样的循环或者处理行为不好的现有代码时别无选择的情况时,选择重用对象而不是创建新对象可以减少垃圾收集器挡住的次数......


29
投票

导致error

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

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

  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

看看有关G1GC的一些更相关的问题

Java 7 (JDK 7) garbage collection and documentation on G1

Java G1 garbage collection in production

Oracle technetwork article for GC finetuning


26
投票

只需在此处设置此选项,即可稍微增加堆大小

运行→运行配置→参数→VM参数

-Xms1024M -Xmx2048M

Xms - 最低限度

Xmx - 最大限制


13
投票

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

  1. 打开eclipse.ini文件
  2. 更改 -Xms40m -Xmx512m -Xms512m -Xmx1024m
  3. 重启Eclipse

See here


11
投票

试试这个

打开build.gradle文件

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

11
投票

以下对我有用。只需添加以下代码段:

android {
        compileSdkVersion 25
        buildToolsVersion '25.0.1'

defaultConfig {
        applicationId "yourpackage"
        minSdkVersion 10
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
dexOptions {
        javaMaxHeapSize "4g"
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.