摘要:那就只能是處理的數據超過了堆區內存上限,按照這個猜測往下分析。主要暴增對象如上圖框出來的地方。符合對象內存一篇文中分析的字節大小。優化自己的程序,使其在運行過程中占用內存盡可能的少。針對異常的具體優化措施。
前言
在正式開始講解關于OutOfMemoryError錯誤之前先來了解下,我在遇到這個異常的背景。
對數據充滿敬畏之心我需要對hive中的數據進行批量操作處理,對于沒有了解過hive的同學來說,有點茫然了。于是按照常規思路開始通過JDBC連接Hive讀取數據 -> 處理數據 -> 寫入數據。
貌似沒有什么不妥的,于是乎噼里啪啦代碼寫好了 -> 調試 -> 驗證 -> 上線批量處理數據。上線處理數據的過程出問題了,為什么半天沒有處理完一條數據?
被坑了,Hive可不是MySQL能夠在ms內返回結果給你,這下傻了,處理一條數據需要幾分鐘到十幾分鐘不等,簡直不能忍啊。
不能忍了能怎么辦,能怎么辦優化解決方案唄。而是借助Hive分布式MR的能力將輸入數據先處理一遍按照讀取的順序給整理好存放到中間表 -> 批量操作中間表 -> 數據寫回。
開始接近了本篇要講解的主題了,進行批量操作數據而導致OutOfMemoryError。
為什么會出現OutOfMemoryError相信有一定編程經驗的開發人員都會遇到這個錯誤,其實出現這個錯誤大家肯定想到的原因:是不是程序寫的有問題產生了大量垃圾對象沒法被JVM回收掉,亦或者是程序的正常邏輯確實需要用到比JVM提供的堆區內存大。
本人在遇到這個錯誤的時候也是這么懷疑過,于是首先去檢查了下自己的代碼,因為邏輯代碼比較少仔細分析后發現程序寫的沒問題,不應該出現無法被JVM回收的內存垃圾。那怎么驗證自己的代碼沒有出現內存垃圾?
通過 jmap -histo:live
?
發現在跳出批量處理數據的邏輯后,所有相關的內存都被回收了,所以確認沒有內存垃圾。
那就只能是處理的數據超過了JVM堆區內存上限,按照這個猜測往下分析。
首先來觀察下機器內存的變化情況jstat -gc
?
確實內存會在一段時間后大量釋放,然后隨著運行又將整個堆區給占滿了。到這里可以確定是由于批量處理數據太多而使線程所擁有的堆區撐爆了。
本來分析應該到這里為止了,但是得知道是什么將堆區給占滿了吧?
什么將內存給占滿了首先通過Java對象內存存儲結構這篇文章了解Java一個對象在內存中分配的字節數為多少。
通過jmap -histo:live
?
主要暴增對象如上圖框出來的地方。
TestObject定義如下:
public class TestObject { private String a; private String b; private String c; private String d; private Integer e; private Integer f; }
從TestObject的定義和上圖存活對象的對比就可以判斷出java.lang.String、java.lang.Integer、[C暴增的原因了。
TestObject size = 194664000/4866600 = 40
String size = 514238640/21426610 = 24
符合Java對象內存一篇文中分析的字節大小。
JVM內存波動JVM內存管理很多前輩都已經講的非常清楚了,根據理論我們來實際窺探下JVM是如何針對內存進行管理的,同時如何進行內存回收。
?
根據JVM對內存的使用策略我們可以看到程序不斷使用內存的過程中堆內存容量在各個部分的波動情況,在新生代/老生代內存達到一定百分比的同時GC回收的回收情況。
觸發條件:
老生代:1043574/1329152 = 0.78 (-XX:CMSInitiatingOccupancyFraction 參數控制容量達到多少進行FGC)
新生代:在Eden區滿后觸發
針對OutOfMemoryError優化手段無非兩種:
加大堆區內存。
優化自己的程序,使其在運行過程中占用內存盡可能的少。
針對OutOfMemoryError異常的具體優化措施。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/67527.html
摘要:直接通過可以造成本機內存溢出。小節內存區域描述異常程序計數器略略略虛擬機棧存放編譯器可知的各種基本類型,對象引用和類型每個線程的棧大小堆存放對象實例最大值最小值運行時常亮池存放編譯期生成的字面量和符號引用,運行期也能放入常量池。 堆溢出 Java堆用于存儲對象實例,只要不斷地創建對象,并且保證GC Roots到對象之間有可達路徑避免垃圾回收,當到達最大堆的容量限制后就會產生Java.l...
摘要:堆堆是用來存儲對象實例的因此如果我們不斷地創建對象并且保證和創建的對象之間有可達路徑以免對象被垃圾回收那么當創建的對象過多時會導致內存不足進而引發異常上面是一個引發異常的代碼我們可以看到它就是通過不斷地創建對象并將對象保存在中防止其被 Java 堆 OutOfMemoryError Java 堆是用來存儲對象實例的, 因此如果我們不斷地創建對象, 并且保證 GC Root 和創建的對象...
摘要:也正是因此,一旦出現內存泄漏或溢出問題,如果不了解的內存管理原理,那么將會對問題的排查帶來極大的困難。 本文已收錄【修煉內功】躍遷之路 showImg(https://segmentfault.com/img/bVbsP9I?w=1024&h=580); 不論做技術還是做業務,對于Java開發人員來講,理解JVM各種原理的重要性不必再多言 對于C/C++而言,可以輕易地操作任意地址的...
摘要:內存溢出分配的內存空間超過系統內存。內存泄漏的原因分析由大塊組成堆,棧,本地方法棧,程序計數器,方法區。內存溢出的原因分析內存溢出是由于沒被引用的對象垃圾過多造成沒有及時回收,造成的內存溢出。小結棧內存溢出程序所要求的棧深度過大導致。 showImg(https://segmentfault.com/img/bVbweuq?w=563&h=300); 前言:JVM中除了程序計數器,其他...
摘要:內存溢出的情況就是從類加載器加載的時候開始出現的,內存溢出分為兩大類和。以下舉出個內存溢出的情況,并通過實例代碼的方式講解了是如何出現內存溢出的。內存溢出問題描述元空間的溢出,系統會拋出。這樣就會造成棧的內存溢出。 導言: 對于java程序員來說,在虛擬機自動內存管理機制的幫助下,不需要自己實現釋放內存,不容易出現內存泄漏和內存溢出的問題,由虛擬機管理內存這一切看起來非常美好,但是一旦...
閱讀 2737·2021-11-11 17:21
閱讀 628·2021-09-23 11:22
閱讀 3591·2019-08-30 15:55
閱讀 1653·2019-08-29 17:15
閱讀 585·2019-08-29 16:38
閱讀 922·2019-08-26 11:54
閱讀 2520·2019-08-26 11:53
閱讀 2768·2019-08-26 10:31