我在执行我的JUnit测试时得到这个错误信息。
java.lang.OutOfMemoryError: GC overhead limit exceeded
我知道什么是 "OutOfMemoryError",但GC开销限制是什么意思?我怎样才能解决这个问题呢?
当花在垃圾收集上的时间太多,而回报太少时,GC就会抛出这个异常,例如,98%的CPU时间花在GC上,而只有不到2%的堆得到恢复。
这个功能的设计是为了防止应用程序在运行了很长一段时间后,由于堆太小,几乎没有进展。
你可以用命令行选项关闭这个功能
-XX:-UseGCOverheadLimit
.
更多信息这里
编辑:看来有人打字比我快:)
如果你确定你的程序中没有[内存泄漏][1],可以尝试。
-Xmx1g
。启用并发低暂停收集器-XX:+UseConcMarkSweepGC
。
在可能的情况下,重用现有的对象,以节省一些内存。
如果有必要,可以通过在命令行添加选项-XX:-UseGCOverheadLimit
来禁用【极限检查】[2]。
[1]: http://www.ibm.com/developerworks/library/j-leaks/ [2]: http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#par_gc.oom
通常是代码的问题。这里有一个简单的例子。
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");
}
}
在Windows7 32位上使用java 1.6.0_24-b07。
java -Xloggc:gc.log GarbageCollector
然后看gc.log
当然,这不是最好的测试,也不是最好的设计,但是当你面临别无选择,只能实现这样一个循环的情况时,或者当处理现有的表现不好的代码时,选择重用对象而不是创建新的对象可以减少垃圾收集器碍事的次数。
导致[错误][1]的原因
GC开销限制超标"。 表示垃圾收集器一直在运行,Java程序的进展非常缓慢。
在一次垃圾收集之后,如果Java进程花费了超过大约98%的时间进行垃圾收集,而且回收的堆量不到2%,并且到目前为止,最近5次(编译时间常数)连续进行垃圾收集,那么就会抛出一个java.lang.OutOfMemoryError。
如果增加堆内存后仍然出现这个错误,请使用内存分析工具,如[MAT]2、[Visual VM][3]等,修复内存泄漏。
将JDK版本升级到最新版本(1.8.x)或至少1.7.x,并使用G1GC算法。 . G1 GC的吞吐量目标是90%的应用时间和10%的垃圾收集时间。
除了用-Xms1g -Xmx2g
来设置堆内存外,还可以试试
-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m。 -XX:ParallelGCThreads=n -XX:ConcGCThreads=n。
请看更多关于G1GC的相关问题。
[甲骨文技术网络关于GC微调的文章][4]
[1]: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks002.html [2]: http://www.eclipse.org/mat/ [3]: https://visualvm.github.io/ [4]: http://www.oracle.com/technetwork/articles/java/g1gc-1984535.html
对我来说,以下步骤是有效的。
eclipse.ini
文件。<!--语言。 lang-none ->
-Xms40m -Xmx512m
到
<!--语言。 lang-none ->
-Xms512m -Xmx1024m
3.重新启动Eclipse
[见此][1]
[1]: https://www.simplified.guide/eclipse/fix-gc-overhead-limit-exceeded
下面的方法对我有用。 只需添加以下代码。
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)。 (-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会导致错误。
这个参考资料可以对某人有所帮助。
我'在Android Studio中工作,在试图生成一个签名的APK进行发布时遇到了这个错误。 我能够顺利地构建和测试一个调试APK,但只要我想构建一个发布APK,构建过程就会持续运行几分钟,然后最终以"Error java.lang.OutOfMemoryError.GC overhead limit exceeded"终止。 GC overhead limit exceeded"。 我增加了虚拟机和Android DEX编译器的堆大小,但问题依然存在。 最后,在喝了很多小时的咖啡之后,发现问题出在我的应用级'build.gradle'。 文件--我把发布构建类型的'minifyEnabled' 参数设置为'false',结果在没有经过缩码处理的代码上运行了Proguard的东西。 过程(见https://developer.android.com/studio/build/shrink-code.html)。 我把'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
}
}
//...
你需要在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**