903

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

java.lang.OutOfMemoryError: GC overhead limit exceeded

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

4

22 回答 22

828

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

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

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

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

查看 Java GC 调整指南,该指南适用于各种 Java 版本,并包含有关此特定问题的部分:

于 2009-09-08T11:39:14.837 回答
237

引用 Oracle 的文章“Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning”

GC 时间过长和 OutOfMemoryError

如果垃圾收集花费的时间过多,并行收集器将抛出 OutOfMemoryError:如果垃圾收集花费的时间超过总时间的 98%,并且回收的堆少于 2%,则会抛出 OutOfMemoryError。此功能旨在防止应用程序长时间运行,同时由于堆太小而几乎没有进展或没有进展。-XX:-UseGCOverheadLimit如有必要,可以通过将选项添加到命令行来禁用此功能。

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

于 2009-09-08T11:43:16.310 回答
103

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

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

如有必要,可以通过将选项添加到命令行来禁用限制检查。-XX:-UseGCOverheadLimit

于 2011-12-14T01:44:17.533 回答
53

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

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

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

现在承认,这不是最好的测试或最好的设计,但是当面对你别无选择只能实现这样一个循环的情况时,或者在处理表现不佳的现有代码时,选择重用对象而不是创建新对象可以减少垃圾收集器阻碍的次数......

于 2011-04-12T19:27:01.417 回答
38

根据Java [8] Platform, Standard Edition Troubleshooting Guide的错误原因:(添加了强调和换行符)

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

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

  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 的更多相关问题

于 2016-02-06T18:06:58.600 回答
31

只需通过在中设置此选项来稍微增加堆大小

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

-Xms1024M -Xmx2048M

Xms - 最小限制

Xmx - 最大限制

于 2014-05-13T10:40:23.373 回答
15

试试这个

打开build.gradle文件

  android {
        dexOptions {
           javaMaxHeapSize = "4g"
        }
   }
于 2016-11-23T18:09:56.527 回答
13

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

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

    -Xms40m
    -Xmx512m
    

    -Xms512m
    -Xmx1024m
    
  3. 重启 Eclipse

看这里

于 2014-12-31T05:09:49.350 回答
12

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

android {
        compileSdkVersion 25
        buildToolsVersion '25.0.1'

defaultConfig {
        applicationId "yourpackage"
        minSdkVersion 10
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
dexOptions {
        javaMaxHeapSize "4g"
    }
}
于 2016-12-27T11:47:41.483 回答
8

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

dexOptions {
    javaMaxHeapSize "1g"
}

到(在gradle中添加这一行)

 dexOptions {
        javaMaxHeapSize "4g"
    }
于 2017-04-07T12:27:08.550 回答
8

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

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

于 2019-09-22T09:53:06.127 回答
6

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

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

不一定非要2048M和32g,随心所欲。

于 2019-07-23T21:03:58.610 回答
5

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”中的一个来指定内存参数,或者使用“g”或“G”来表示 GB。如果您指定“MB”或“GB”,您的设置将不起作用。有效参数如下所示:

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

此参考可能对某人有所帮助。

于 2019-10-10T09:09:00.440 回答
1

我在 Android Studio 中工作,并在尝试生成已签名的 APK 以供发布时遇到此错误。我能够毫无问题地构建和测试调试 APK,但是一旦我想构建发布 APK,构建过程将连续运行几分钟,然后最终以“错误 java.lang.OutOfMemoryError: GC超出开销限制”。我增加了 VM 和 Android DEX 编译器的堆大小,但问题仍然存在。最后,经过几个小时和大杯咖啡,问题出在我的应用程序级“build.gradle”文件中——我将发布构建类型的“minifyEnabled”参数设置为“false”,因此运行 Proguard 的东西关于尚未通过代码收缩过程的代码(请参阅https://developer.android.)。我将“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
    }
}

//...
于 2018-01-07T22:33:42.217 回答
1

要增加 IntelliJ IDEA 中的堆大小,请按照以下说明进行操作。它对我有用。

对于 Windows 用户,

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

idea64.exe.vmoptions

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

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

这就对了 !!

于 2018-06-14T13:16:24.140 回答
1

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

您还可以通过打开 cmd-> 2g(2gigabytes) 来更改 Java 堆,set _java_opts -Xmx2g
具体取决于程序的复杂性

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

在此处输入图像描述

于 2020-02-27T02:40:16.643 回答
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**
于 2016-04-13T09:52:39.197 回答
0

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

于 2017-06-12T22:45:37.163 回答
0

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

将 kotlin 版本更新到可用的最新版本。https://blog.jetbrains.com/kotlin/category/releases/

它完成了。

于 2019-11-25T03:41:41.373 回答
0

@Buhb 我在它的主要方法中的一个普通的spring-boot Web应用程序中复制了这个。这是代码:

public static void main(String[] args) {
    SpringApplication.run(DemoServiceBApplication.class, args);
    LOGGER.info("hello.");
    int len = 0, oldlen=0;
    Object[] a = new Object[0];
    try {
        for (; ; ) {
            ++len;
            Object[] temp = new Object[oldlen = len];
            temp[0] = a;
            a = temp;
        }
    } catch (Throwable e) {
        LOGGER.info("error: {}", e.toString());
    }
}

引起来的示例代码也来自 oracle java8 语言规范。

于 2021-09-11T05:17:23.433 回答
0

使用 Oracle Web 逻辑服务器时出现此错误。我正在分享我的答案以供参考,以防有人最终在这里寻找解决方案。

因此,如果您尝试启动 Oracle Web 逻辑服务器并遇到此错误,那么您只需增加为运行服务器设置的初始堆大小和最大堆大小。

转到 - > C:\Oracle\Middleware\Oracle_Home\user_projects\domains\wl_server\bin

打开setDomainEnv.cmd

检查设置 USER_MEM_ARGS值,如果小于则

设置 USER_MEM_ARGS="-Xms128m – Xmx8192m ${MEM_DEV_ARGS} ${MEM_MAX_PERM_SIZE}"

这意味着您的初始堆大小设置为 128 MB,最大堆大小为 8GB。现在,只需保存文件并重新启动服务器。如果它没有解决问题,请尝试增加大小或寻找优化服务的方法。

对于参考,请查看此链接:https ://docs.oracle.com/cd/E49933_01/server.770/es_install/src/tins_postinstall_jvm_heap.html

编辑:检查您是否能够在运行服务器时看到更新的 java args。就像这样在此处输入图像描述 如果它像以前一样出现,那么通过简单的搜索和替换来替换 setDoaminEnv.cmd 中显示的值。

于 2021-11-06T18:35:38.300 回答
-5

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

于 2019-02-26T17:23:05.750 回答