成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java堆內(nèi)存溢出梗概分析

云計(jì)算 虛擬化
任何像內(nèi)存溢出這種非確定性的、時(shí)有時(shí)無的問題對(duì)于事后的分析都是一個(gè)挑戰(zhàn)。所以,最好的處理內(nèi)存溢出的方法是讓 JVM 虛擬機(jī)轉(zhuǎn)儲(chǔ)一份 JVM 虛擬機(jī)內(nèi)存狀態(tài)的堆文件。

任何使用過基于 Java 的企業(yè)級(jí)后端應(yīng)用的軟件開發(fā)者都會(huì)遇到過這種低劣、奇怪的報(bào)錯(cuò),這些報(bào)錯(cuò)來自于用戶或是測(cè)試工程師: java.lang.OutOfMemoryError:Java heap space。

為了弄清楚問題,我們必須返回到算法復(fù)雜性的計(jì)算機(jī)科學(xué)基礎(chǔ),尤其是“空間”復(fù)雜性。如果我們回憶,每一個(gè)應(yīng)用都有一個(gè)最壞情況特征。具體來說,在存儲(chǔ)維度方面,超過推薦的存儲(chǔ)將會(huì)被分配到應(yīng)用程序上,這是不可預(yù)測(cè)但尖銳的問題。這導(dǎo)致了堆內(nèi)存的過度使用,因此出現(xiàn)了"內(nèi)存不夠"的情況。

[[226270]]

這種特定情況最糟糕的部分是應(yīng)用程序不能修復(fù),并且將崩潰。任何重啟應(yīng)用的嘗試 - 甚至使用***內(nèi)存(-Xmx option)- 都不是長(zhǎng)久之計(jì)。如果不明白什么導(dǎo)致了堆使用的膨脹或突出,內(nèi)存使用穩(wěn)定性(即應(yīng)用穩(wěn)定性)就不能保障。于是,什么才是更有效的理解關(guān)于內(nèi)存的編程問題的途徑?當(dāng)內(nèi)存溢出時(shí),明白應(yīng)用程序的內(nèi)存堆和分布情況才能回答這個(gè)問題。

在這一前提下,我們將聚焦以下方面:

  • 當(dāng)內(nèi)存溢出時(shí),獲取到 Java 進(jìn)程中的堆轉(zhuǎn)儲(chǔ)。
  • 明白應(yīng)用程序正在遭遇的內(nèi)存問題的類型。
  • 使用一個(gè)堆分析器,可以使用 Eclipse MAT 這個(gè)優(yōu)秀的開源項(xiàng)目來分析內(nèi)存溢出的問題。

配置應(yīng)用,為堆分析做準(zhǔn)備

任何像內(nèi)存溢出這種非確定性的、時(shí)有時(shí)無的問題對(duì)于事后的分析都是一個(gè)挑戰(zhàn)。所以,***的處理內(nèi)存溢出的方法是讓 JVM 虛擬機(jī)轉(zhuǎn)儲(chǔ)一份 JVM 虛擬機(jī)內(nèi)存狀態(tài)的堆文件。

Sun HotSpot JVM 有一種方法可以引導(dǎo) JVM 轉(zhuǎn)儲(chǔ)內(nèi)存溢出時(shí)的堆狀態(tài)到一個(gè)文件中。其標(biāo)準(zhǔn)格式為 .hprof 。所以,為了實(shí)現(xiàn)這種操作,向 JVM 啟動(dòng)項(xiàng)中添加 XX:+HeapDumpOnOutOfMemoryError 。因?yàn)閮?nèi)存溢出可能經(jīng)過很長(zhǎng)一段時(shí)間才會(huì)發(fā)生,向生產(chǎn)系統(tǒng)增加這一選項(xiàng)也是必須的。

如果堆轉(zhuǎn)儲(chǔ) .hprof 文件必須被寫在一個(gè)特定的文件系統(tǒng)位置,那么就添加目錄途徑到 XX:HeapDumpPath 。只需確保該應(yīng)用對(duì)于指定目錄途徑始終擁有寫入權(quán)限。

原因分析

101:了解內(nèi)存溢出錯(cuò)誤的本質(zhì)

當(dāng)嘗試去評(píng)估和了解一個(gè)內(nèi)存溢出錯(cuò)誤時(shí),***做的事情應(yīng)該是觀察內(nèi)存增長(zhǎng)特征。根據(jù)情況做出可能性的評(píng)估:

尖峰狀:這種類型的內(nèi)存溢出在某種類型的加載上會(huì)是比較激烈的。當(dāng) JVM 分配內(nèi)存給 20 個(gè)用戶時(shí),應(yīng)用程序可以正常運(yùn)行。但是,如果到第 100 個(gè)用戶時(shí)可能會(huì)遭遇到內(nèi)存峰值,從而導(dǎo)致內(nèi)存溢出。有兩種可能的辦法去解決這個(gè)問題。

泄露:由于某些編程問題,內(nèi)存使用隨著時(shí)間的推移逐漸增加。

擁有良性垃圾回收機(jī)制的健康圖表

健康一段時(shí)間后,隨時(shí)間推移而泄露的圖表

 

引起內(nèi)存使用凸起、導(dǎo)致內(nèi)存溢出的內(nèi)存圖表

在我們了解導(dǎo)致使用率激增的內(nèi)存問題的本質(zhì)之后,基于從對(duì)分析中得到的推斷,下面的這些方法或許可以用來避免遭遇內(nèi)存溢出的錯(cuò)誤。

解決內(nèi)存問題

修復(fù)引起內(nèi)存溢出的代碼:由于應(yīng)用在某段時(shí)間內(nèi)增量添加了一個(gè)對(duì)象而沒有清除其引用(來自正在運(yùn)行的應(yīng)用程序的對(duì)象引用),導(dǎo)致不得不修復(fù)程序錯(cuò)誤。例如,這一錯(cuò)誤可能是插入了一個(gè)哈希表, 其中的業(yè)務(wù)對(duì)象會(huì)逐漸增加,然而業(yè)務(wù)邏輯和事務(wù)在完成之后并沒有刪除這些對(duì)象。

增加內(nèi)存***值作為一種修復(fù)方法。在了解了運(yùn)行內(nèi)存特征和堆之后,可能必須增加分配的***堆內(nèi)存來避免再次發(fā)生內(nèi)存溢出,因?yàn)橥扑]的***內(nèi)存值不能夠滿足應(yīng)用程序的穩(wěn)定性。所以,應(yīng)用程序可能不得不基于堆分析器的評(píng)估,將 Java -Xmx 的 flag 信息更新成一個(gè)更高值后再來運(yùn)行。

堆分析

下面我們將詳細(xì)分析如何使用一個(gè)堆分析工具來分析堆轉(zhuǎn)儲(chǔ)。在示例中,將使用到 Eclipse 基金會(huì)的開源工具 MAT 。

使用 MAT 進(jìn)行堆分析

是時(shí)候進(jìn)行深入探討了。我們將通過一系列的步驟,幫助探索在 MAT 中的不同表現(xiàn)和視圖,以獲取一個(gè)堆內(nèi)存溢出的示例并思考分析。

1. 打開內(nèi)存溢出錯(cuò)誤發(fā)生時(shí)產(chǎn)生的 .hprof 堆文件。確保復(fù)制轉(zhuǎn)儲(chǔ)文件到一個(gè)專門的文件夾下,因?yàn)?MAT 會(huì)創(chuàng)建許多索引文件:文件 -> 打開

2. 打開轉(zhuǎn)儲(chǔ)文件,有內(nèi)存泄漏嫌疑報(bào)告和組件報(bào)告的選項(xiàng)。選擇運(yùn)行泄漏嫌疑報(bào)告。

3. 泄漏嫌疑表打開后,在預(yù)覽窗口的餅狀圖會(huì)展示在每個(gè)對(duì)象基礎(chǔ)上保留內(nèi)存的分布情況。它顯示了內(nèi)存中的***對(duì)象(擁有***保留內(nèi)存的對(duì)象 —— 累積的內(nèi)存和引用的對(duì)象)。

4. 上面的餅圖通過聚合擁有***內(nèi)存引用(本身內(nèi)存和總內(nèi)存)的對(duì)象來展示 3 個(gè)問題嫌疑人。

讓我們逐一分情況查看,評(píng)估它是否是內(nèi)存溢出錯(cuò)誤的根本原因。

可疑點(diǎn) 1

由 “<system class loader>” 加載的 454,570 個(gè) “java.lang.ref.Finalizer” 實(shí)例占用了 790,205,576(47.96%)個(gè)字節(jié)。

這就是告訴我們有 454,570 個(gè) JVM finalizer(終結(jié)器)實(shí)例占據(jù)了分配的應(yīng)用內(nèi)存的近 50 %。

假設(shè)讀者知道 Java Finalizer 是做什么的,上面的信息會(huì)讓我們明白什么呢?

入門閱讀:http://stackoverflow.com/questions/2860121/why-do-finalizers-have-a-severe-performance-penalty

本質(zhì)上,開發(fā)者編寫了一些定制化的終結(jié)器去釋放一個(gè)實(shí)例的資源。這些由終結(jié)器收集的實(shí)例不在 JVM 使用單獨(dú)隊(duì)列的垃圾回收算法的范圍之內(nèi)。實(shí)際上,這種途徑比起垃圾回收機(jī)制的清理路徑更長(zhǎng)。所以現(xiàn)在我們應(yīng)該努力搞清楚這些終結(jié)器到底終結(jié)了什么?

也或許是可疑點(diǎn) 2 ,占據(jù)了 20% 的 sun.security.ssl.SSLSocketImpl 。我們能確認(rèn)是否這些就是要被終結(jié)器終結(jié)的實(shí)例嗎?

可疑點(diǎn) 2

現(xiàn)在,讓我們打開在 MAT 頂部的工具按鈕下面的 Dominator 視圖。我們會(huì)看到所有的列出的類實(shí)例,經(jīng)由 MAT 解析展示出有效的堆存儲(chǔ)。

下一步,在 Dominator 視圖,我們嘗試?yán)斫?java.lang.Finalizer 和 sun.security.ssl.SSLSocketImpl 之間的關(guān)系。我們右鍵點(diǎn)擊 sun.security.ssl.SSLSocketImpl 這一列,打開 GC Roots -> exclude soft/weak references。

現(xiàn)在,MAT 將會(huì)開始繪制內(nèi)存的圖表來顯示 GC root 的路徑以及它所對(duì)應(yīng)的實(shí)例引用。這會(huì)被顯示在另外一個(gè)頁面上,顯示的引用如下:

如上面引用鏈顯示,實(shí)例 SSLSocketImpl 來自于 java.lang.ref.Finalizer,整個(gè) SSLSocketImpl 實(shí)例大約占用了 88k。我們還注意到 finalizer 鏈?zhǔn)且粋€(gè)針鏈表數(shù)據(jù)結(jié)構(gòu)它指向下一個(gè)實(shí)例。

推論:在這一點(diǎn)上,我們有一個(gè)明確的感覺,Java finalizer 試圖在收集 SSLSocketImpl 對(duì)象。為了解釋為什么還有很多信息沒有被收集到,我開始檢查代碼。

檢查代碼

代碼檢查需要查看是不是由 socket 套接字被關(guān)閉導(dǎo)致的。在這種情況下,它顯示與 I/O 相關(guān)的所有流,需要被正確地關(guān)閉。在一點(diǎn)上,我們懷疑 JVM 是始作俑者。實(shí)際上,在 Open JDK 6.0.XX 的 GC(垃圾收集器)上的代碼中有一個(gè) BUG。

我希望這篇文章給你一個(gè)模式來分析 Java 應(yīng)用中的錯(cuò)誤是由堆存儲(chǔ)還是內(nèi)部問題導(dǎo)致的。希望你使用堆分析愉快!

擴(kuò)展閱讀

Shallow heap (淺堆) vs. Retained Heap (保留堆)

淺堆是一個(gè)對(duì)象消耗的內(nèi)存。根據(jù)情況,一個(gè)對(duì)象需要 32 位或 64 位(取決于其操作系統(tǒng)架構(gòu)),對(duì)于整型為 4 字節(jié),對(duì)于 Long 型為 8 字節(jié)等等。依據(jù)堆轉(zhuǎn)儲(chǔ)格式,其內(nèi)存大小(比如,向 8 對(duì)齊)或許適應(yīng)于更好地塑造虛擬機(jī)的真實(shí)消耗。

X 的保留集合是當(dāng) X 被垃圾回收時(shí),那些將要被移除的對(duì)象集合。

X 的保留堆是在 X 的保留集合中所有對(duì)象的淺堆之和,也就是 X 存留的內(nèi)存。

總體講,一個(gè)對(duì)象的淺堆就是其在堆中的大小。同一個(gè)對(duì)象的保留大小就是當(dāng)對(duì)象被垃圾回收時(shí)堆內(nèi)存的總量。

一些對(duì)象的主要集合,比如某一特定類的所有對(duì)象、或是由某一特定類加載器加載的所有類的所有對(duì)象、或僅僅是一些任意的對(duì)象,它們的保留集是如果那些主要集的所有對(duì)象變得不可接近時(shí)所釋放的對(duì)象集。

保留集包括這些對(duì)象和僅通過這些對(duì)象才能獲取的其它對(duì)象。保留集的大小是包含在保留集中的所有對(duì)象的堆的大小。

責(zé)任編輯:武曉燕 來源: 21世紀(jì)技術(shù)官
相關(guān)推薦

2020-05-09 13:49:00

內(nèi)存空間垃圾

2013-08-02 10:06:36

Android內(nèi)存溢出

2021-06-28 06:45:06

內(nèi)存溢出內(nèi)存泄露JavaScript

2024-03-11 08:22:40

Java內(nèi)存泄漏

2015-08-06 14:54:50

JavaScript分析工具OneHeap

2022-12-26 14:41:38

Linux內(nèi)存

2023-05-29 07:17:48

內(nèi)存溢出場(chǎng)景

2020-09-28 10:20:30

漏洞

2015-09-25 16:18:36

2023-09-22 17:34:37

內(nèi)存remove方法

2019-02-26 14:33:22

JVM內(nèi)存虛擬機(jī)

2021-05-26 08:02:03

ThreadLocal多線程多線程并發(fā)安全

2020-10-25 09:39:49

漏洞分析

2017-01-11 14:02:32

JVM源碼內(nèi)存

2013-07-23 06:47:55

Android內(nèi)存機(jī)制Android堆和棧Android開發(fā)學(xué)習(xí)

2011-12-15 16:55:04

TomcatJavajsp

2021-03-06 10:25:19

內(nèi)存Java代碼

2011-03-18 19:50:32

ScalaJVMQt

2009-06-03 15:52:34

堆內(nèi)存棧內(nèi)存Java內(nèi)存分配

2024-09-09 09:41:03

內(nèi)存溢出golang開發(fā)者
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 亚洲午夜精品 | 91精品国产777在线观看 | 在线看一区二区三区 | 精品成人一区二区 | 欧美一级毛片久久99精品蜜桃 | 三级视频在线观看 | 久久久久久亚洲精品 | 久久久久久黄 | 欧美精选一区二区 | 国产激情在线播放 | 欧美综合自拍 | 欧美一区二区在线视频 | 91久久精品一区二区二区 | 国产一区二区三区四区区 | 亚洲一区 | 成人欧美一区二区 | 亚洲成人激情在线观看 | 四虎在线观看 | 国产成人一区二区三区精 | 91资源在线 | 亚洲国产成人精品女人久久久野战 | 99热热热热 | 国产精品成人一区二区三区 | 国产又色又爽又黄又免费 | 狠狠狠色丁香婷婷综合久久五月 | 亚洲精品一区在线 | 91丨国产 | 国产小视频精品 | 亚洲 精品 综合 精品 自拍 | 爱爱无遮挡| 在线免费观看一区二区 | 国产精品久久一区二区三区 | 黄色一级大片在线免费看产 | 一级片免费网站 | 日韩在线中文字幕 | 欧美伦理一区 | 中文字幕福利视频 | www.亚洲成人网 | 国产精品一区一区 | 欧美国产激情 | 欧美成人精品一区 |