当我执行JUnit测试时,我得到了这个错误消息:

java.lang.OutOfMemoryError: GC overhead limit exceeded

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


当前回答

您还可以通过将此添加到gradle中来增加内存分配和堆大小。属性文件:

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

它不需要2048M和32g,你想要多大就有多大。

其他回答

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

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

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

为了防止应用程序占用CPU时间而不做任何事情,JVM抛出这个错误,以便您有机会诊断问题。

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

请查看Java GC调优指南,该指南可用于各种Java版本,其中包含关于此特定问题的部分:

Java 11调优指南中有针对不同垃圾收集器的过量GC的专门章节: 用于并联集热器 用于同步标记扫描(CMS)收集器 对于垃圾优先(G1)收集器,没有提到这种特定的错误条件。 Java 8调优指南及其过量GC部分 Java 6调优指南及其过量GC部分。

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

你也可以通过打开cmd-> set _java_opts - xmx2g来改变java堆 2g(2gb),这取决于程序的复杂程度

尽量少使用常数变量和临时变量

引用Oracle的文章“Java SE 6 HotSpot[tm]虚拟机垃圾收集调优”:

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.

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

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

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次

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