簡體   English   中英

錯誤 java.lang.OutOfMemoryError:超出 GC 開銷限制

[英]Error java.lang.OutOfMemoryError: GC overhead limit exceeded

我在執行JUnit測試時收到此錯誤消息:

java.lang.OutOfMemoryError: GC overhead limit exceeded

我知道OutOfMemoryError是什么,但是 GC 開銷限制是什么意思? 我該如何解決這個問題?

此消息意味着由於某種原因垃圾收集器占用了過多的時間(默認為進程所有 CPU 時間的 98%)並且在每次運行中回收的內存非常少(默認為堆的 2%)。

這實際上意味着您的程序停止執行任何進度並且一直忙於僅運行垃圾收集。

為了防止您的應用程序在沒有完成任何事情的情況下占用 CPU 時間,JVM 會拋出此Error以便您有機會診斷問題。

我見過這種情況發生的極少數情況是,一些代碼在已經非常受內存限制的環境中創建了大量臨時對象和大量弱引用對象。

查看 Java GC 調優指南,該指南適用於各種 Java 版本,並包含有關此特定問題的部分:

引用 Oracle 的文章“Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning”

GC 時間過長和 OutOfMemoryError

如果垃圾收集花費了太多時間,並行收集器將拋出 OutOfMemoryError:如果超過 98% 的總時間花費在垃圾收集上,而回收的堆不到 2%,則會拋出 OutOfMemoryError。 此功能旨在防止應用程序長時間運行而由於堆太小而進展甚微或沒有進展。 如有必要,可以通過在命令行中添加選項-XX:-UseGCOverheadLimit來禁用此功能。

編輯:看起來有人可以比我打字更快:)

如果您確定程序中沒有內存泄漏,請嘗試:

  1. 增加堆大小,例如-Xmx1g
  2. 啟用並發低暫停收集器-XX:+UseConcMarkSweepGC
  3. 盡可能重用現有對象以節省一些內存。

如有必要,可以通過在命令行中添加選項-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>(); // 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 次

現在承認,這不是最好的測試或最好的設計,但是當面臨這樣的情況時,您別無選擇,只能實現這樣的循環,或者在處理表現不佳的現有代碼時,選擇重用對象而不是創建新對象可以減少垃圾收集器妨礙的次數...

根據Java [8] Platform, Standard Edition 故障排除指南中的錯誤原因:(添加了強調和換行符)

[...]“超出GC開銷限制”表示垃圾收集器一直在運行並且Java程序進展非常緩慢。

在垃圾回收之后,如果Java 進程花費了大約 98% 以上的時間進行垃圾回收,並且如果它正在回收不到 2% 的堆並且到目前為止一直在做最后 5 個(編譯時間常數)連續垃圾集合,然后拋出java.lang.OutOfMemoryError [...]

  1. 如果當前堆不夠,則增加堆大小
  2. 如果在增加堆內存后仍然出現此錯誤,請使用內存分析工具,MAT (內存分析器工具)、 Visual VM等並修復內存泄漏。
  3. 將 JDK 版本升級到最新版本 (1.8.x) 或至少 1.7.x 並使用 G1GC 算法。 . G1 GC 的吞吐量目標是 90% 的應用程序時間和 10% 的垃圾收集時間
  4. 除了使用 - Xms1g -Xmx2g設置堆內存Xms1g -Xmx2g ,還可以嘗試

    -XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m -XX:ParallelGCThreads=n -XX:ConcGCThreads=n

看看一些關於 G1GC 的更多相關問題

只需通過在其中設置此選項來稍微增加堆大小

運行 → 運行配置 → 參數 → VM 參數

-Xms1024M -Xmx2048M

Xms - 最低限度

Xmx - 最大限制

試試這個

打開build.gradle文件

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

對我來說,以下步驟有效:

  1. 打開eclipse.ini文件
  2. 改變

    -Xms40m -Xmx512m

    -Xms512m -Xmx1024m
  3. 重啟 Eclipse

看這里

以下對我有用。 只需添加以下代碼段:

android {
        compileSdkVersion 25
        buildToolsVersion '25.0.1'

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

在 build.gradle(Module:app) 文件中增加 javaMaxHeapsize

dexOptions {
    javaMaxHeapSize "1g"
}

到(在gradle中添加這一行)

 dexOptions {
        javaMaxHeapSize "4g"
    }

解決了:
只需添加
org.gradle.jvmargs=-Xmx1024m

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

您還可以通過將其添加到gradle.properties文件來增加內存分配和堆大小:

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

不一定要2048M和32g,想多大就多大。

Java 堆大小描述(xms、xmx、xmn)

-Xms size in bytes

Example : java -Xms32m

設置 Java 堆的初始大小。 默認大小為 2097152 (2MB)。 這些值必須是 1024 字節 (1KB) 的倍數且大於 1024 字節。 (-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 會導致錯誤。

此參考資料可能對某人有所幫助。

我在 Android Studio 中工作並在嘗試生成已簽名的 APK 以供發布時遇到此錯誤。 我能夠毫無問題地構建和測試調試 APK,但是一旦我想構建發布版 APK,構建過程就會連續運行幾分鍾,然后最終以“Error java.lang.OutOfMemoryError: GC超出開銷限制”。 我增加了 VM 和 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
    }
}

//...

要在 IntelliJ IDEA 中增加堆大小,請遵循以下說明。 它對我有用。

對於 Windows 用戶,

轉到IDE安裝的位置並搜索以下內容。

idea64.exe.vmoptions

編輯文件並添加以下內容。

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

這就對了 !!

您可以嘗試通過參考此圖像對服務器設置進行更改,並增加內存大小以處理以黃色突出顯示的進程更改

您還可以通過打開 cmd-> set _java_opts -Xmx2g來更改 java 堆
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**

在 Netbeans 中,設計最大堆大小可能會有所幫助。 轉到運行=>設置項目配置=>自定義 在彈出窗口的Run中,轉到VM Option ,填寫-Xms2048m -Xmx2048m 它可以解決堆大小問題。

我不知道這是否仍然相關,但只是想分享對我有用的東西。

將 kotlin 版本更新為可用的最新版本。 https://blog.jetbrains.com/kotlin/category/releases/

它完成了。

@Buhb 我在其主要方法中的普通 spring-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\\Middleware\\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。 現在,只需保存文件並重新啟動服務器。 如果它沒有解決問題,請嘗試增加大小或尋找優化服務的方法。

對於參考,請檢查此鏈接: https : //docs.oracle.com/cd/E49933_01/server.770/es_install/src/tins_postinstall_jvm_heap.html

編輯:檢查您是否能夠在運行服務器時看到更新的 java args。 像這樣在此處輸入圖片說明 如果它像以前一樣出現,那么通過簡單的搜索和替換來替換 setDoaminEnv.cmd 中顯示的值。

重新啟動我的 MacBook 為我解決了這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM