簡體   English   中英

如何處理“java.lang.OutOfMemoryError: Java heap space”錯誤?

[英]How to deal with "java.lang.OutOfMemoryError: Java heap space" error?

我正在Java 5上編寫客戶端Swing應用程序(圖形字體設計器)。 最近,我遇到了java.lang.OutOfMemoryError: Java heap space錯誤,因為我對 memory 的使用並不保守。 用戶可以打開無限數量的文件,程序將打開的對象保留在 memory 中。經過快速研究,我發現5.0 Java 虛擬機中的人體工程學和其他人在 Windows 機器上說 JVM 默認最大堆大小為64MB

鑒於這種情況,我應該如何處理這個約束?

我可以使用命令行選項將最大堆大小增加到 java,但這需要確定可用的 RAM 並編寫一些啟動程序或腳本。 此外,增加到某個有限的最大值並不能最終解決這個問題。

我可以重寫我的一些代碼以頻繁地將對象持久保存到文件系統(使用數據庫是一回事)以釋放 memory。它可以工作,但它可能也需要很多工作。

如果你能指出上述想法的細節或一些替代方案,如自動虛擬 memory,動態擴展堆大小,那就太好了。

最終,無論您在什么平台上運行,您總是可以使用有限的最大堆。 在 Windows 32 位中,這大約是2GB (不是特別是堆,而是每個進程的總內存量)。 碰巧Java選擇使默認值更小(大概是為了讓程序員無法創建具有失控內存分配的程序而不會遇到這個問題並且必須檢查他們正在做什么)。

因此,鑒於您可以采取多種方法來確定所需的內存量或減少正在使用的內存量。 垃圾收集語言(如 Java 或 C#)的一個常見錯誤是保留對不再使用的對象的引用,或者在可以重用它們時分配許多對象。 只要對象有對它們的引用,它們就會繼續使用堆空間,因為垃圾收集器不會刪除它們。

在這種情況下,您可以使用 Java 內存分析器來確定程序中的哪些方法正在分配大量對象,然后確定是否有辦法確保不再引用它們,或者首先不分配它們。 我過去使用的一個選項是“JMP” http://www.khelekore.org/jmp/

如果您確定分配這些對象是有原因的,並且您需要保留引用(取決於您在做什么,這可能是這種情況),您只需要在啟動程序時增加最大堆大小。 但是,一旦您進行了內存分析並了解了您的對象是如何分配的,您應該對您需要多少內存有一個更好的了解。

一般來說,如果你不能保證你的程序會在有限的內存中運行(可能取決於輸入大小),你總會遇到這個問題。 只有在用盡所有這些之后,您才需要考慮將對象緩存到磁盤等。此時,您應該有一個很好的理由說“我需要 Xgb 內存”,而您無法通過改進來解決它您的算法或內存分配模式。 通常,這通常僅適用於在大型數據集(如數據庫或某些科學分析程序)上運行的算法,然后緩存和內存映射 IO 等技術變得有用。

使用命令行選項-Xmx運行 Java,該選項設置堆的最大大小。

詳情請看這里

您可以為每個項目指定您的項目需要多少堆空間

以下是Eclipse Helios/Juno/Kepler的:

鼠標右鍵點擊

 Run As - Run Configuration - Arguments - Vm Arguments, 

然后添加這個

-Xmx2048m

增加堆大小不是“修復”,而是“石膏”,100% 是臨時的。 它會在其他地方再次崩潰。 為避免這些問題,請編寫高性能代碼。

  1. 盡可能使用局部變量。
  2. 確保您選擇了正確的對象(例如:String、StringBuffer 和 StringBuilder 之間的選擇)
  3. 為您的程序使用良好的代碼系統(例如:使用靜態變量 VS 非靜態變量)
  4. 其他可以在你的代碼上工作的東西。
  5. 嘗試使用多線程移動

大警告 ---- 在我的辦公室,我們發現(在某些 Windows 機器上)我們不能為 Java 堆分配超過 512m 的空間。 事實證明,這是由於其中一些機器上安裝了卡巴斯基反病毒產品。 卸載該 AV 產品后,我們發現我們可以分配至少 1.6gb,即-Xmx1600m (m 是強制性的,否則會導致另一個錯誤“Too small initial heap”)有效。

不知道其他 AV 產品是否會發生這種情況,但大概是因為 AV 程序在每個地址空間中保留了一小塊內存,從而阻止了單個非常大的分配。

我想添加來自 oracle 故障排除文章的建議。

線程 thread_name 中的異常: java.lang.OutOfMemoryError:Java 堆空間

詳細消息 Java 堆空間指示無法在 Java 堆中分配對象。 此錯誤不一定意味着內存泄漏

可能的原因:

  1. 簡單的配置問題,指定的堆大小對於應用程序來說是不夠的。

  2. 應用程序無意中持有對對象的引用,這可以防止對象被垃圾收集。

  3. 過度使用終結器

此錯誤的另一個潛在來源是過度使用終結器的應用程序。 如果一個類有一個 finalize 方法,那么該類型的對象在垃圾回收時不會回收它們的空間

垃圾回收之后,對象將排隊等待最終確定,這將在稍后發生。 終結器由服務終結隊列的守護線程執行。 如果終結器線程無法跟上終結隊列,那么 Java 堆可能會填滿,並且會拋出這種類型的OutOfMemoryError異常。

可能導致這種情況的一種情況是,當應用程序創建高優先級線程時,會導致終結隊列以比終結器線程服務該隊列的速率更快的速率增加。

VM 參數在 Eclipse 中為我工作。 如果您使用的是 eclipse 3.4 版,請執行以下操作

轉到Run --> Run Configurations -->然后選擇 maven build 下的項目 --> 然后選擇選項卡“JRE” --> 然后輸入-Xmx1024m

或者,您可以執行Run --> Run Configurations --> select the "JRE" tab -->然后輸入 - Xmx1024m

這應該會增加所有構建/項目的內存堆。 上述內存大小為 1 GB。 你可以優化你想要的方式。

是的,使用-Xmx可以為 JVM 配置更多內存。 確保您不會泄漏或浪費內存。 進行堆轉儲並使用Eclipse Memory Analyzer分析您的內存消耗。

請按照以下步驟操作:

  1. 從 tomcat/bin 打開catalina.sh

  2. 將 JAVA_OPTS 更改為

    JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC"
  3. 重啟你的tomcat

我在其他地方讀到了你可以嘗試的地方 - 捕獲 java.lang.OutOfMemoryError 並在 catch 塊上,你可以釋放所有你知道可能會使用大量內存的資源,關閉連接等等,然后執行System.gc()然后重新嘗試您要執行的任何操作。

另一種方法是,雖然我不知道這是否可行,但我目前正在測試它是否適用於我的應用程序。

想法是通過調用已知會增加可用內存的 System.gc() 來進行垃圾收集。 您可以在執行內存吞噬代碼后繼續檢查。

//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);

Runtime runtime = Runtime.getRuntime();

if(runtime.freeMemory()<minRunningMemory)
 System.gc();

默認情況下,開發 JVM 使用小尺寸和小配置來實現其他與性能相關的功能。 但是對於生產,您可以調整例如(另外它可以存在應用程序服務器特定的配置)->(如果仍然沒有足夠的內存來滿足請求並且堆已經達到最大大小,則會發生 OutOfMemoryError)

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        set java thread stack size

-XX:ParallelGCThreads=8
-XX:+CMSClassUnloadingEnabled
-XX:InitiatingHeapOccupancyPercent=70
-XX:+UnlockDiagnosticVMOptions
-XX:+UseConcMarkSweepGC
-Xms512m
-Xmx8192m
-XX:MaxPermSize=256m (in java 8 optional)

例如:在 linux 平台上進行生產模式的首選設置。

以這種方式下載和配置服務器后http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/

1.在文件夾/opt/tomcat/bin/上創建setenv.sh文件

   touch /opt/tomcat/bin/setenv.sh

2.打開並寫入此參數以設置首選模式。

nano  /opt/tomcat/bin/setenv.sh 

export CATALINA_OPTS="$CATALINA_OPTS -XX:ParallelGCThreads=8"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+CMSClassUnloadingEnabled"
export CATALINA_OPTS="$CATALINA_OPTS -XX:InitiatingHeapOccupancyPercent=70"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UnlockDiagnosticVMOptions"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseConcMarkSweepGC"
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxMetaspaceSize=256M"

3. service tomcat restart

請注意,JVM 使用的內存不僅僅是堆。 例如,Java 方法、線程堆棧和本機句柄被分配在與堆分開的內存中,以及 JVM 內部數據結構中。

如果你來這里是從 REACT NATIVE 搜索這個問題。

那我想你應該這樣做

cd android/ && ./gradlew clean && cd ..

在 Java 中解決OutOfMemoryError的簡單方法是使用 JVM 選項-Xmx512M增加最大堆大小,這將立即解決您的 OutOfMemoryError。 當我在構建項目時在 Eclipse、Maven 或 ANT 中遇到 OutOfMemoryError 時,這是我首選的解決方案,因為根據項目的大小,您很容易耗盡內存。

這是增加 JVM 最大堆大小的示例,如果您在 java 應用程序中設置堆大小,最好將 -Xmx 與 -Xms 的比例保持為 1:1 或 1:1.5。

export JVM_ARGS="-Xms1024m -Xmx1024m"

參考鏈接

如果您需要在運行時監控內存使用情況, java.lang.management包提供的MBeans可用於監控 VM 中的內存池(例如,eden 空間、tenured generation 等),以及垃圾收集行為。

這些 MBean 報告的可用堆空間會因 GC 行為而有很大差異,特別是如果您的應用程序生成了許多后來被 GC-ed 的對象。 一種可能的方法是在每次完全 GC 之后監視可用堆空間,您可以使用它來決定通過持久化對象來釋放內存。

最終,您最好的選擇是在性能保持可接受的情況下盡可能限制您的記憶保留。 正如之前的評論所指出的,內存總是有限的,但你的應用程序應該有一個處理內存耗盡的策略。

我從java堆大小遇到了同樣的問題。

如果您使用的是 java 5(1.5),我有兩個解決方案。

  1. 只需安裝 jdk1.6 並轉到 eclipse 的首選項並設置您安裝的 jav1 1.6 的 jre 路徑。

  2. 檢查你的 VM 參數,讓它成為任何東西。 只需在 VM 參數中存在的所有參數的下方添加一行 -Xms512m -Xmx512m -XX:MaxPermSize=...m(192m)。

我認為它會工作...

在 android studio 添加/更改gradle.properties (Global Properties)末尾的這一行:

...
org.gradle.jvmargs=-XX\:MaxHeapSize\=1024m -Xmx1024m 

如果它不起作用,您可以使用大於 1024 的堆大小重試。

將此行添加到您的 gradle.properties 文件

org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

它應該工作。 您可以相應地更改 MaxPermSize 以解決您的堆問題

請注意,如果您在部署情況下需要此功能,請考慮使用 Java WebStart(帶有“ondisk”版本,而不是網絡版本 - 在 Java 6u10 及更高版本中可能),因為它允許您以交叉方式指定 JVM 的各種參數平台方式。

否則,您將需要一個特定於操作系統的啟動器來設置您需要的參數。

android/gradle.properties中添加以下代碼:

org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.configureondemand=true

對於netbeans,您可以設置最大堆大小來解決問題。

轉到'運行',然后-->'設置項目配置'-->'自定義'-->彈出窗口的'運行'-->'VM選項'-->填寫'-Xms2048m -Xmx2048m' .

在我的情況下,它通過在 intellij 設置中為Shared build process heap size分配更多內存來解決。

轉到 intellij 設置 > 編譯器 > 共享構建進程堆大小

在此處輸入圖像描述

如果您繼續分配和保留對對象的引用,您將填滿您擁有的任何內存量。

一種選擇是在切換選項卡時關閉和打開透明文件(您只保留指向文件的指針,當用戶切換選項卡時,您關閉並清理所有對象......這會使文件更改速度變慢...但是...),並且可能只在內存中保留 3 或 4 個文件。

您應該做的另一件事是,當用戶打開文件時,加載它並攔截任何 OutOfMemoryError,然后(因為無法打開文件)關閉該文件,清理其對象並警告用戶他應該關閉未使用的文件。

您動態擴展虛擬內存的想法並不能解決問題,因為機器的資源有限,所以您應該小心處理內存問題(或者至少要小心處理)。

我在內存泄漏方面看到的一些提示是:

--> 請記住,如果您將某些內容放入集合中,然后忘記了它,那么您仍然對它有一個強引用,因此請取消集合、清理它或用它做一些事情......如果沒有,您會發現一個內存泄漏很難找到。

--> 也許,使用帶有弱引用的集合(weakhashmap...)可以幫助解決內存問題,但您必須小心,因為您可能會發現您要查找的對象已被收集。

--> 我發現的另一個想法是開發一個持久性集合,該集合存儲在使用最少且透明加載的數據庫對象上。 這可能是最好的方法...

如果這個問題在 Wildfly 8 和 JDK1.8 中發生,那么我們需要指定 MaxMetaSpace 設置而不是 PermGen 設置。

例如,我們需要在 Wildfly 的 setenv.sh 文件中添加以下配置。 JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"

有關更多信息,請查看Wildfly 堆問題

安卓工作室

File -> Invalidate Caches and Restart 為我解決了它:)

如果在執行 junit 測試后立即發生此錯誤,則應執行Build -> Rebuild Project

如果在 react-native 中生成 APK 期間出現此錯誤,請 cd 進入項目中的 android 文件夾並執行以下操作:

./gradlew clean

然后

./gradlew assembleRelease

如果錯誤仍然存​​在,請重新啟動您的機器。

如果您使用的是 Android Studio,只需在gradle.properties文件中添加這些行

org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

如果一切都失敗了,除了增加最大堆大小之外,還要嘗試增加交換大小。 對於 Linux,截至目前,相關說明可以在https://linuxize.com/post/create-a-linux-swap-file/中找到。

如果您要在嵌入式平台上編譯一些大的東西,這會有所幫助。

如果您在啟動 eclipse birt 時遇到此錯誤 1-您將進入 eclipse 配置文件 2-您必須打開 eclipse.init 3-修改了 RAM 內存,您可以增加它,我舉個例子。

我的舊信息是:-Xmx128m -XX:MaxPermSize=128m

我操作的新修改:

-Xmx512m -XX:MaxPermSize=512m

當我在瀏覽器中啟動報告時,此修改將允許我解析 Java 堆空間。

謝謝

當您的數據庫連接池已滿時,也會出現 Java OOM 堆空間問題。

我遇到了這個問題,因為我的 Hikari 連接池(升級到 Spring boot 2.4.* 時)已滿,無法再提供連接(所有活動連接仍在等待從數據庫中獲取結果)。

問題是我們在 JPA 存儲庫中的一些本機查詢包含ORDER BY ?#{#pageable}升級后需要很長時間才能獲得結果。

從 JPA 存儲庫中的所有本機查詢中刪除ORDER BY ?#{#pageable}並解決 OOM 堆空間問題以及連接池問題。

在 Intellij 中,它僅通過提供“構建項目”對我有用

在此處輸入圖像描述

暫無
暫無

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

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