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

2022-08-31 05:00:55

我在一个程序中收到此错误,该程序创建了几个(数十万个)HashMap对象,每个对象有几个(15-20)个文本条目。在提交到数据库之前,必须收集所有字符串(不要分解成较小的数量)。

根据Sun的说法,错误发生了“如果在垃圾回收中花费了太多时间:如果超过98%的总时间用于垃圾回收,并且不到2%的堆被恢复,则将抛出OutOfMemoryError。

显然,可以使用命令行将参数传递给 JVM

  • 通过“-Xmx1024m”(或更多)增加堆大小,或
  • 通过“-XX:-UseGCOverheadLimit”完全禁用错误检查。

第一种方法工作正常,第二种方法在另一个java.lang.OutOfMemoryError中结束,这次是关于堆的。

那么,问题:对于特定的用例(即,几个小的HashMap对象),是否有任何编程替代方案?例如,如果我使用HashMap clear()方法,问题就会消失,但存储在HashMap中的数据也会消失!:-)

StackOverflow 中的相关主题也讨论了这个问题。


答案 1

您基本上耗尽了内存来顺利运行该过程。想到的选项:

  1. 像你提到的指定更多的内存,尝试介于两者之间的东西,比如先-Xmx512m
  2. 尽可能处理较小批次的对象,以便一次处理HashMap
  3. 如果你有很多重复的字符串,在将它们放入HashMap
  4. 使用 HashMap(int initialCapacity, float loadFactor) 构造函数来调整您的情况

答案 2

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

dexOptions {
        javaMaxHeapSize "4g"
}

到您的 :build.gradle

android {
    compileSdkVersion 23
    buildToolsVersion '23.0.1'

    defaultConfig {
        applicationId "yourpackage"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        multiDexEnabled true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    packagingOptions {

    }

    dexOptions {
        javaMaxHeapSize "4g"
    }
}