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

时间:2009-09-08 11:34:28

标签: java garbage-collection out-of-memory heap-memory

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

java.lang.OutOfMemoryError: GC overhead limit exceeded

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

21 个答案:

答案 0 :(得分:690)

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

这实际上意味着您的程序停止了任何进度,并且一直忙着只运行垃圾收集。

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

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

查看this article了解详情(具体为this part)。

答案 1 :(得分:191)

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

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

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

更多信息here

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

答案 2 :(得分:79)

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

  1. 增加堆大小,例如-Xmx1g
  2. 启用并发低暂停收集器-XX:+UseConcMarkSweepGC
  3. 尽可能重用现有对象以节省一些内存。
  4. 如有必要,可以通过在命令行中添加选项-XX:-UseGCOverheadLimit来禁用limit check

答案 3 :(得分:38)

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

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次

现在已经获得批准,这不是最好的测试或最好的设计,但面对的情况是你别无选择,只能实现这样的循环或处理行为不当的现有代码,选择重用对象而不是创建新的那些可以减少垃圾收集器妨碍的次数......

答案 4 :(得分:28)

error

的原因
  

超出GC开销限制&#34;表示垃圾收集器一直在运行,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
    
  5. 查看一些有关G1GC的更多相关问题

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

    Java G1 garbage collection in production

    Oracle technetwork article for GC finetuning

答案 5 :(得分:26)

通过在

中设置此选项,只需稍微增加堆大小

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

-Xms1024M -Xmx2048M

Xms - 最低限额

Xmx - 最高限额

答案 6 :(得分:13)

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

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

    -Xms40m
    -Xmx512m
    

    -Xms512m
    -Xmx1024m
    
  3. 重启Eclipse

  4. See here

答案 7 :(得分:10)

试试这个

打开build.gradle文件

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

答案 8 :(得分:10)

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

android {
        compileSdkVersion 25
        buildToolsVersion '25.0.1'

defaultConfig {
        applicationId "yourpackage"
        minSdkVersion 10
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
dexOptions {
        javaMaxHeapSize "4g"
    }
}

答案 9 :(得分:4)

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

dexOptions {
    javaMaxHeapSize "1g"
}

to(在gradle中添加此行)

 dexOptions {
        javaMaxHeapSize "4g"
    }

答案 10 :(得分:1)

重新启动MacBook为我解决了此问题。

答案 11 :(得分:1)

Java堆大小描述(xms,xmx,xmn)

-Xms size in bytes

Example : java -Xms32m

设置Java堆的初始大小。 默认大小为2097152(2MB)。 该值必须是1024字节(1KB)的倍数,并且大于1024字节(1KB)。 (-server标志将默认大小增加到32M。)

-Xmn size in bytes

Example : java -Xmx2m

设置Eden代的初始Java堆大小。 默认值为640K。 (-server标志将默认大小增加到2M。)

-Xmx size in bytes

Example : java -Xmx2048m

设置Java堆可以增长的最大大小。 默认大小为64M。 (-server标志将默认大小增加到128M。) 最大堆限制约为2 GB(2048MB)。

Java内存参数(xms,xmx,xmn)格式

设置Java堆大小时,应使用字母“ m”或“ M”(对于MB)或“ g”或“ G”(对于GB)之一来指定内存参数。如果您指定“ MB”或“ GB”,则您的设置将无效。有效的参数如下所示:

-Xms64m或-Xms64M -Xmx1g或-Xmx1G 也可以使用2048MB指定2GB 另外,请确保在指定参数时仅使用整数。使用-Xmx512m是有效选项,但-Xmx0.5g会导致错误。

此参考资料可能对某人有用。

答案 12 :(得分:0)

我正在使用apache-tomcat-8.5.37。我面临着同样的错误

  

java.lang.outofmemoryerror:超出了gc开销限制

我上面已经读过有关解决方案的说明

  

增加堆大小,例如-Xmx1g。启用并发低   暂停收集器-XX:+ UseConcMarkSweepGC。重用现有对象   可以节省一些内存。如有必要,可以进行极限检查   通过在命令中添加选项-XX:-UseGCOverheadLimit禁用   线。

此解决方案对某人有用吗?需要解决此问题的建议。

答案 13 :(得分:0)

您还可以通过将其添加到gradle.properties文件中来增加内存分配和堆大小:

org.gradle.jvmargs=-Xmx2048M -XX\:MaxHeapSize\=32g

它不必是2048M和32g,可以根据需要设置它的大小。

答案 14 :(得分:0)

已解决:
只需添加
 org.gradle.jvmargs=-Xmx1024m

 gradle.properties
如果不存在,请创建它。

答案 15 :(得分:0)

我不知道这是否仍然有意义,只是想分享对我有用的东西。

将kotlin版本更新为最新版本。 https://blog.jetbrains.com/kotlin/category/releases/

就完成了。

答案 16 :(得分:0)

您可以尝试通过参考此图像在服务器设置上进行更改,并增加用于处理的内存大小 过程更改以黄色突出显示

您还可以通过打开cmd-> set _java_opts -Xmx2g
对Java堆进行更改 2g(2gbytes),取决于您程序的复杂程度

尝试使用较少的常量和临时变量

enter image description here

答案 17 :(得分:-1)

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

答案 18 :(得分:-1)

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

简而言之,我必须更改我的应用级&#39; build.gradle&#39;来自的文件:     //...

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
    }
}

//...

答案 19 :(得分:-1)

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

对于Windows用户,

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

idea64.exe.vmoptions

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

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

就是这样!!

答案 20 :(得分:-2)

在Netbeans中,设计最大堆大小可能会有所帮助。转到运行 =&gt; 设置项目配置 =&gt; 自定义。在其弹出窗口的 Run 中,转到 VM Option ,填写-Xms2048m -Xmx2048m。它可以解决堆大小问题。