摘要:一說明當虛擬機申請不到內存空間的時候,會報堆內存溢出。記錄次數不讓進程結束,便于使用分析工具來查看內存情況使用的版本報錯信息運行結果表明,運行到次時,出現了堆內存溢出。
一、說明
當虛擬機申請不到內存空間的時候,會報堆內存溢出: OutOfMemoryError:java heap space。
常見的原因:http://outofmemory.cn/c/java-...
我測試到時候,運行在 16G 內存的機器上。JVM 堆內存 默認為物理內存的1/4,即 16 * 1/4 = 4G
JDK 8的 JVM 在 JDK 7 的基礎上從堆內存中移除了永久代(Perm Generation),替換為了堆內存之外的元空間(Metaspace),元空間是堆外直接內存,不受堆內存的限制,只受物理內存的限制,可以提供更大的空間。二、原因及解決辦法
OutOfMemoryError 異常的常見原因:
加載的數據過大。如:加載的文件或者圖片過大、一次從數據庫取出過多數據
代碼存在死循環或循環產生過多的對象
解決方法
增加jvm的內存大小,使用 -Xmx 和 -Xms 來設置
檢查代碼中是否有死循環或遞歸調用。
檢查是否有大循環重復產生新對象實體。
檢查對數據庫查詢中,是否有一次獲得全部數據的查詢。一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。這個問題比較隱蔽,在上線前,數據庫中數據較少,不容易出問題,上線后,數據庫中數據多了,一次查詢就有可能引起內存溢出。因此對于數據庫查詢盡量采用分頁的方式查詢。
檢查List、Map等集合對象是否有使用完后,未清除的問題。List、MAP等集合對象會始終存有對對象的引用,使得這些對象不能被GC回收。
三、代碼示例/**java堆溢出實例 * 原理:java的堆是用來存放對象實例的,所以我們只要做到以下三點就可以使堆溢出: * 1、限制堆的大小,不可擴展 * 2、不斷新建對象 * 3、保持對象存活不被回收 * 對應的,我們需要: * 1、改變JVM的啟動參數,將堆的最小值和最大值設成一樣,這樣就可以避免堆自動擴展(其實不一樣也可以) * 2、不斷產生對象 * 3、使用一個List來保存對象,保持對象存活 * * JVM配置參數: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError * */ public class HeapOom { public static void main(String[] args) { // 此list實例會存放在堆內存中 Listlist = new ArrayList<>(); int i = 0; boolean flag = true; while (flag) { try { i++; // 每次增加一個1M大小的數組對象 list.add(new byte[1024 * 1024]); } catch (Throwable e) { // catch 捕獲的是 Throwable,而不是 Exception。因為 OutOfMemoryError 不屬于 Exception 的子類。 e.printStackTrace(); flag = false; // 記錄次數 System.out.println("count=" + i); } } // 不讓進程結束,便于使用分析工具來查看內存情況 try { Thread.sleep(24 * 60 * 60 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
使用的 java 1.8.0_171 版本:
$ java -version java version "1.8.0_171" Java(TM) SE Runtime Environment (build 1.8.0_171-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
報錯信息:
count=3316 java.lang.OutOfMemoryError: Java heap space at com.song.HeapOom.main(HeapOom.java:21)
運行結果表明,運行到 3316 次時,出現了堆內存溢出。由于每次增加1M內存。粗略估計:程序大約使用3G內存時,出現了內存溢出情況。
通過jmap或VisualVM 者工具可以查看內存情況:最后可以看出,老年代內存使用情況,大約使用了2709MB,使用率近100%。從而導致了 OutOfMemoryError
TIPS:下面查看內存時,由于使用工具查看內存的時間不是同一時間,所以內存使用量有細微差別1. 使用jmap查看的內存信息
$ jmap -heap 3428 Attaching to process ID 3428, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.66-b18 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 4261412864 (4064.0MB) NewSize = 88604672 (84.5MB) MaxNewSize = 1420296192 (1354.5MB) OldSize = 177733632 (169.5MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 637009920 (607.5MB) used = 637009920 (607.5MB) free = 0 (0.0MB) 100.0% used From Space: capacity = 11010048 (10.5MB) used = 0 (0.0MB) free = 11010048 (10.5MB) 0.0% used To Space: capacity = 11010048 (10.5MB) used = 0 (0.0MB) free = 11010048 (10.5MB) 0.0% used PS Old Generation // 老年代內存使用情況,大約使用了2709MB,使用率近100%(導致OutOfMemoryError) capacity = 2841116672 (2709.5MB) used = 2840991320 (2709.38045501709MB) free = 125352 (0.11954498291015625MB) 99.99558793198338% used 4955 interned Strings occupying 422328 bytes.2. 使用 VisualVM 查看的內存信息
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75094.html
摘要:內存溢出分配的內存空間超過系統內存。內存泄漏的原因分析由大塊組成堆,棧,本地方法棧,程序計數器,方法區。內存溢出的原因分析內存溢出是由于沒被引用的對象垃圾過多造成沒有及時回收,造成的內存溢出。小結棧內存溢出程序所要求的棧深度過大導致。 showImg(https://segmentfault.com/img/bVbweuq?w=563&h=300); 前言:JVM中除了程序計數器,其他...
摘要:內存溢出的情況就是從類加載器加載的時候開始出現的,內存溢出分為兩大類和。以下舉出個內存溢出的情況,并通過實例代碼的方式講解了是如何出現內存溢出的。內存溢出問題描述元空間的溢出,系統會拋出。這樣就會造成棧的內存溢出。 導言: 對于java程序員來說,在虛擬機自動內存管理機制的幫助下,不需要自己實現釋放內存,不容易出現內存泄漏和內存溢出的問題,由虛擬機管理內存這一切看起來非常美好,但是一旦...
摘要:第章內存區域與內存溢出異常運行時數據區域虛擬機在執行程序的過程中會把它所管理的內存劃分為若干個不同的數據區域。即對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例。 第2章 Java內存區域與內存溢出異常 2.2 運行時數據區域 Java虛擬機在執行Java程序的過程中會把它所管理的內存劃分為若干個不同的數據區域。根據《Java虛擬機規范(Java SE 7版)...
摘要:也正是因此,一旦出現內存泄漏或溢出問題,如果不了解的內存管理原理,那么將會對問題的排查帶來極大的困難。 本文已收錄【修煉內功】躍遷之路 showImg(https://segmentfault.com/img/bVbsP9I?w=1024&h=580); 不論做技術還是做業務,對于Java開發人員來講,理解JVM各種原理的重要性不必再多言 對于C/C++而言,可以輕易地操作任意地址的...
閱讀 2469·2021-11-15 11:38
閱讀 2844·2021-11-02 14:44
閱讀 3821·2021-09-26 10:13
閱讀 3060·2021-08-13 15:02
閱讀 780·2019-08-30 15:56
閱讀 1450·2019-08-30 15:53
閱讀 2363·2019-08-30 13:01
閱讀 3193·2019-08-29 12:57