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

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

java.lang.OutOfMemoryError: GC overhead limit exceeded

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

1150367 次浏览

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

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

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

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

查看JavaGC调优指南,它可用于各种Java版本,并包含有关此特定问题的部分:

引用Oracle的文章"JavaSE 6 HotSpot[tm]虚拟机垃圾收集调整"

过多的GC时间和OutOfMemoryError

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

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

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

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>(); // WORSElist.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位上使用Java1.60_24-b07。

java -Xloggc:gc.log GarbageCollector

再看看gc.log

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

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

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

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

如果需要,可以通过将选项-XX:-UseGCOverheadLimit添加到命令行来禁用极限检查

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

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

-Xms1024M -Xmx2048M

xms-最小限制

Xmx-最大限制

对我来说,以下步骤奏效了:

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

    -Xms40m-Xmx512m

    -Xms512m-Xmx1024m
  3. Restart Eclipse

See here

根据Java[8]平台,标准版故障排除指南错误的原因:(添加了强调和换行符)

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

在垃圾回收机制之后,如果Java过程花费超过98%的时间用于垃圾回收机制并且如果它正在回收不到2%的堆并且到目前为止一直在执行最后5个(编译时间常量)连续垃圾回收,则抛出java.lang.OutOfMemoryError

  1. 增加堆大小如果当前堆不够。
  2. 如果在增加堆内存后仍然出现此错误,请使用内存分析工具(如(内存分析工具)、可视化虚拟机等)并修复内存泄漏。
  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

你需要增加内存大小在J开发者去setDomainEnv.cmd

set WLS_HOME=%WL_HOME%\serverset 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**

试试这个

打开build.gradle文件

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

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

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

增加javaMaxHeapsize在您的build.gradle(模块:应用程序)文件

dexOptions {javaMaxHeapSize "1g"}

to(在gradle中添加此行)

 dexOptions {javaMaxHeapSize "4g"}

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

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

简而言之,我必须更改我的应用程序级“build.gradle”文件://…

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

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

要在IntelliJ IDEA中增加堆大小,请按照以下说明进行操作。

对于Windows用户,

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

idea64.exe.vmoptions

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

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

就是它!!

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

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

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

它不一定是2048M和32克,让它像你想要的那么大。

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

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

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会导致错误。

这个参考可能对某人有帮助。

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

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

就完成了。

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

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

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

在此处输入图片描述

@Buhb我在它的main方法中的一个普通的sping-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语言规范。

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

因此,如果您尝试启动Oracle Web逻辑服务器并出现此错误,那么您只需增加用于运行服务器的初始和最大堆大小集。

转到->C:\Oracle\中间件\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。现在,只需保存文件并重新启动服务器。如果它没有解决问题,请尝试增加大小或寻找优化服务的方法。

对于ref,检查此链接:https://docs.oracle.com/cd/E49933_01/server.770/es_install/src/tins_postinstall_jvm_heap.html

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