was java heap space_实战项目中Java heap space错误的解决
部標GPS通訊系統在上線之后,經過不斷調試,終于穩定運行一段時間,后來又遇到了Java?heap space錯誤異常!日志如下:
說明系統中有未釋放的對象。如何找出這些未釋放對象以及監控JVM堆內存,優化代碼釋放內存對象呢?還有JVM的垃圾回收機制是如何運作的呢?
首先在系統啟動運行的時候打開記錄GC詳細信息,運行腳本如下:
看看GC詳細日志,當GC到13400多次的時候新生代和老生代的堆內存幾乎用滿了,頻繁觸發Full GC (Ergonomics)?,直到沒有內存空間給新生對象了。所以JVM拋出了內存溢出錯誤!進而導致程序崩潰。
首先簡單了解下JVM垃圾回收機制:
從上圖可以看出?GC?的主要收集區域,包括 PSYoungGen(年輕代)、ParOldGen(老年代)、Metaspace(元數據區)。
新生代:新創建的對象都是用新生代分配內存,Eden空間不足時,觸發Minor GC,這時會把存活的對象轉移進幸存者Survivor區。
老年代:老年代用于存放經過多次Minor GC之后依然存活的對象。
新生代的GC(Minor GC):新生代通常存活時間較短基于Copying算法進行回收,所謂Copying算法就是掃描出存活的對象,并復制到一塊新的完全未使用的空間中,對應于新生代,就是在Eden和FromSpace或ToSpace之間copy。
新生代采用空閑指針的方式來控制GC觸發,指針保持最后一個分配的對象在新生代區間的位置,當有新的對象要分配內存時,用于檢查空間是否足夠,不夠就觸發GC。當連續分配對象時,對象會逐漸從Eden到Survivor,最后到老年代。
老年代的GC(Major GC/Full GC):老年代與新生代不同,老年代對象存活的時間比較長、比較穩定,因此采用標記(Mark)算法來進行回收,所謂標記就是掃描出存活的對象,然后再進行回收未被標記的對象,
回收后對用空出的空間要么進行合并、要么標記出來便于下次進行分配,總之目的就是要減少內存碎片帶來的效率損耗。
附上堆結構圖:
至此,在已經嘗試了將Java虛擬機中Xms(初始堆大小-2G)和Xmx(最大堆大小-4G)參數調大之后也無果,只能從代碼入手,?對象一直堆積于老年代未被釋放,應該是代碼中對象未被釋放。
為了找出代碼中未被釋放的對象,這里運用到了內存監控工具jconsole和內存堆對象統計工具jmap。
jconsole.exe位于bin目錄下,用法也挺簡單的,用于調優后的監控還不錯,這里留個圖不做介紹了
這里運用jmap(jdk自帶的jvm內存分析的工具),將程序堆對象統計出來的結果如下:
發現到代碼問題:應該是解析協議的時候CanDataItem對象不斷被new出來,使用完了以后并未被GC回收留在老生代,
找到CanDataItem使用完成的地方做了如下修改:
修改代碼再將T808Message等類用完了的地方做了釋放,之后終于解決了問題!修改代碼以后再次使用jmap統計如下,正常了!
附?-?jmap輸出中class?name非自定義類的說明:
BaseType?CharacterTypeInterpretation
B
byte
signed?byte
C
char
Unicode?character
D
double
double-precision?floating-point?value
F
float
single-precision?floating-point?value
I
int
integer
J
long
long?integer
L;
reference
an?instance?of?class
S
short
signed?short
Z
boolean
true?or?false
[
reference
one?array?dimension,[I表示int[]
總結導致java.lang.OutOfMemoryError異常的常見原因有以下幾種:
內存中加載的數據量過于龐大,如一次從數據庫取出過多數據;
集合類中有對對象的引用,使用完后未清空,使得JVM不能回收;
代碼中存在死循環或循環產生過多重復的對象實體-----(本例中);
使用的第三方軟件中的BUG;
啟動參數內存值設定的過小;
至此問題總算解決了,通常情況下,Java開發人員并不需要去關心JVM是如何運行的。即使不理解JVM的工作原理,也不會給開發人員帶來過多困惑。Java程序員更容易忽視基礎技術。
“蚓無爪牙之利,筋骨之強,上食埃土,下飲黃泉,用心一也。蟹六跪而二螯,非蛇蟮之穴無可寄托者,用心躁也”。對于技術人員來說,如果長期忽略自身技術的根基而去一昧地追求高層框架技術,這無疑是舍本求末的做法。
JVM的出現,為程序員屏蔽了操作系統與硬件的細節,使得程序員從諸如內存管理這樣的繁瑣任務中解放出來。但這不并等同于允許Java程序員放棄對基礎的重視。
事實上,任何平臺的程序員都應當了解平臺的基本特性、實現機制以及接口,這是提高自身修養的必經之路。對于Java程序員來說,我們還是需要多多了解JVM。
了解JVM的基本實現機制,不僅對于解決實際應用中諸如GC等虛擬機問題時有直接幫助,還有利于我們更好地理解語言本身。
轉載請注明出處!謝謝!https://www.cnblogs.com/lys_013/p/9605352.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的was java heap space_实战项目中Java heap space错误的解决的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java初学课程_作为java新手应该学
- 下一篇: java 转换 unicode_JAVA