我执行JUnit测试时收到以下错误消息:
java.lang.OutOfMemoryError: GC overhead limit exceeded
我知道是什么OutOfMemoryError
,但是GC开销限制是什么意思?我该如何解决?
OutOfMemoryError
情况下,增加堆不是有效的解决方案:用尽本机线程和用尽perm gen(与堆分开)是两个示例。对过于宽泛的陈述要谨慎OutOfMemoryErrors
; 有一系列意想不到的事情可以导致它们。
我执行JUnit测试时收到以下错误消息:
java.lang.OutOfMemoryError: GC overhead limit exceeded
我知道是什么OutOfMemoryError
,但是GC开销限制是什么意思?我该如何解决?
OutOfMemoryError
情况下,增加堆不是有效的解决方案:用尽本机线程和用尽perm gen(与堆分开)是两个示例。对过于宽泛的陈述要谨慎OutOfMemoryErrors
; 有一系列意想不到的事情可以导致它们。
Answers:
此消息表示由于某种原因,垃圾收集器占用了过多的时间(默认情况下为进程所有CPU时间的98%),并且每次运行时恢复的内存很少(默认为堆的2%)。
这实际上意味着您的程序停止任何进展,并且一直在忙于仅运行垃圾回收。
为了防止您的应用程序浪费CPU时间而不做任何事情,JVM抛出此错误,Error
以便您有机会诊断问题。
我见过这种情况的罕见情况是,某些代码在已经非常受内存限制的环境中创建了大量的临时对象和大量的弱引用对象。
查阅Java GC调整指南,该指南可用于各种Java版本,并包含有关此特定问题的部分:
引用Oracle的文章“ Java SE 6 HotSpot [tm]虚拟机垃圾收集优化”:
过多的GC时间和OutOfMemoryError
如果在垃圾回收上花费了太多时间,则并行收集器将抛出OutOfMemoryError:如果在垃圾回收中花费了总时间的98%以上,而回收的堆少于2%,则将抛出OutOfMemoryError。此功能旨在防止应用程序长时间运行,而由于堆太小而几乎没有进展,甚至没有进展。如有必要,可以通过
-XX:-UseGCOverheadLimit
在命令行中添加选项来禁用此功能。
编辑:看起来有人可以比我更快地输入:)
-XX:
在几个命令行选项的开头是一个标志,表明此选项是高度特定于VM的并且不稳定(在将来的版本中可能会有所更改,恕不另行通知)。无论如何,该-XX:-UseGCOverheadLimit
标志告诉VM禁用GC开销限制检查(实际上是“关闭”),而您的-Xmx
命令只是增加了堆空间。在后一种情况下,GC开销检查仍在运行,这听起来像是更大的堆解决了您的情况下的GC崩溃问题(这并不总是有帮助)。
如果您确定程序中没有内存泄漏,请尝试:
-Xmx1g
。 -XX:+UseConcMarkSweepGC
。如有必要,可以通过在命令行中添加选项来禁用限制检查-XX:-UseGCOverheadLimit
。
List
在循环内部创建对象导致GC被调用39次而不是22次。
通常是代码。这是一个简单的例子:
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
现在,这不是最佳的测试或最佳的设计,但是当您除了别无选择,只能实现这样的循环或者处理行为不佳的现有代码时,选择重用对象而不是创建新对象可以减少垃圾收集器阻塞的次数...
gc.log
文件中的行数开始的。我的测试总体上显示的次数要少得多,但是对BETTER来说,“触发”次数最少,现在,BAD比现在的WORST更“糟糕”。我的罪状:BAD:26,更糟糕:22,BETTER 21
List<Double> list
在外部循环中而不是在外部循环之前定义了,并触发了39个垃圾回收。
根据Java [8] Platform,Standard Edition故障排除指南,错误的原因:(添加了强调和换行符)
超过“ GC开销限制”表示垃圾收集器一直在运行,并且Java程序的进度非常缓慢。
进行垃圾回收之后,如果Java进程花费了其大约98%的时间用于垃圾回收,并且正在恢复的内存少于2%,并且到目前为止已经执行了最后5个(编译时间常数)连续垃圾集合,然后
java.lang.OutOfMemoryError
抛出a。[...]
除了使用-设置堆内存之外Xms1g -Xmx2g
,请尝试
-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m
-XX:ParallelGCThreads=n -XX:ConcGCThreads=n
看看有关G1GC的一些其他相关问题
只需在以下位置设置此选项即可稍微增加堆大小
运行→运行配置→参数→VM参数
-Xms1024M -Xmx2048M
Xms-最小限制
Xmx-最大限制
arguments
选项卡...我们应该怎么做才能做到这一点?
以下对我有用。只需添加以下代码段:
android {
compileSdkVersion 25
buildToolsVersion '25.0.1'
defaultConfig {
applicationId "yourpackage"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions {
javaMaxHeapSize "4g"
}
}
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会导致错误。
此参考资料可能对某人有所帮助。
解决:
只需添加
org.gradle.jvmargs=-Xmx1024m
,
gradle.properties
如果不存在,则创建它。
我在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
}
}
//...
您可以尝试通过参考此图像在服务器设置上进行更改,并增加以黄色突出显示的处理过程更改的内存大小
您还可以通过打开cmd->来更改Java堆 set _java_opts -Xmx2g
2g(2gigabytes)具体取决于程序的复杂性
尝试使用较少的常量和临时变量
您需要在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**
我不知道这是否仍然有意义,只是想分享对我有用的东西。
将Kotlin版本更新为最新版本。https://blog.jetbrains.com/kotlin/category/releases/
完成了。