探究内存泄露—Part2—分析问题
本文由ImportNew-黄索远翻译自captaindebug ImportNew注:如果你也对Java技术翻译分享感兴趣,欢迎加入我们的Java开发小组。参与方式请查看小组简介。 如果你看过这篇博客的第一部分,就会知道在展示的内存泄露示例代码使用生产者-消费者模型创建了一个模拟
本文由 ImportNew - 黄索远 翻译自 captaindebug
ImportNew注:如果你也对Java技术翻译分享感兴趣,欢迎加入我们的 Java开发 小组。参与方式请查看小组简介。
如果你看过这篇博客的第一部分,就会知道在展示的内存泄露示例代码使用生产者-消费者模型创建了一个模拟股票交易的应用,所有的交易命令都被存入一个虚拟的数据库中。示例代码故意留下了一个缺陷(OrderRecord线程处理一条命令后sleep一段时间),使得OrderRecord线程消费命令的速度跟不上OrderFeed线程生产命令的速度。这就意味着存储命令的队列会变得越来越长,直到最后内存溢出程序崩溃。问题是,如果只看我的代码,确实能够很轻松得看出哪里出了差错;但是如果出问题的代码你从未看过并且代码又长又复杂,加之没有监控线程来帮助你观察队列大小或者其他内部信息,这时该怎么办呢?
下面向大家介绍分析程序内存泄露问题的三个步骤:
提取发生内存泄露的服务器的转储文件。
用这个转储文件生成报告。
分析生成的报告。
有几个工具能帮你生成堆转储文件,分别是:
jconsole
Jvisualvm
Eclipse Memory Analyser Tool(MAT)
用jconsole提取堆转储文件
将jconsole关联你的应用:单击MBeans选项卡打开com.sun.management包,点击HotSpotDiagnostic,点击Operations选择dumpHeap。这时你将会看到dumpHeap操作:它接受两个参数p0和p1。在p0的编辑框内输入一个堆转储的文件名,然后按下DumpHeap命令。
用jvisualvm提取堆转储文件
连接示例代码,右键点击你的应用,在左侧的“application”窗格中选择“Heap Dump”。
注意:如果你在发生内存泄露的服务器上有一个远程连接,那么jvisualvm将会把转出文件保存在远程机器(假设这是一台unix机器)上的/tmp目录下。你不得不将这个文件通过FTP传送到你的机器上,然后再进行研究。
用MAT来提取堆转储文件
jconsole和jvisualvm本身就是JDK的一部分,而MAT或者称作“内存分析工具”,是一个基于eclipse的工具。你可以从eclipse.org下载。
最新版本的MAT需要你在电脑上安装JDk1.6。如果你用的是Java1.7版本也不用担心,因为它会自动为你安装1.6版本,并且不会和安装好了的1.7版本产生冲突。
使用MAT的时候,只需要点击“Aquire Heap Dump”,然后遵循指示就可以了。
远程连接
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
何时提取堆转存文件
这需要耗费一点心力和运气。如果太早提取了堆转储文件,那么你将不能发现问题。因为它们被合法,非泄露类的实例屏蔽了。不过也不能等待太久,因为提取堆转储文件需要占用内存,进行提取操作的时候可能会导致你的应用崩溃。
最好的办法是将jconsole连接到你的应用程序并监控堆的占用情况,知道它看起来像在崩溃的边缘。这样很容易就能监控到,因为没有发生内存泄露时,三个堆部分指标都是绿色的。
分析转储文件
现在轮到MAT发挥作用了,因为它本身就是被设计用来分析堆转储文件的。要打开和分析一个堆转储文件,选择File选项下的Heap Dump选项。选择了你要打开的文件后,你将会看到如下三个选项:
选择Leak Suspect Report选项。在MAT翻腾几秒后,会生成这样的一个页面:
如饼状图显示:在示例中,疑似有一处发生了内存泄露。也许你会想,这样的做法只有在代码受到控制的情况下才可取。毕竟这只是个例子,这又能说明什么呢?好吧,我承认在这个例子里,所有的问题都是可见的;线程a占用了98.7MB内存,其他线程用了1.5MB。在实际情况中,你得到的图表是这样的。
下一步要做的就是挖得更深一点……
如上图所示,报告的下一部分告诉我们,有一个LinkedBlockQueue占用了98.46%的内存。想要进一步的探究,点击Details>>。
可以看到,问题确实是出在我们的orderQueue上。这个队列里存储了所有生成的虚拟命令,并且可以被我们上篇博文里提到的三个线程OrderFeed、OrderRecord、OrderMonitor访问。
那么一切都清楚了,MAT告诉我们:示例代码中有一个LinkedBlockQueue,这个队列用尽了所有的内存,从而导致了严重的问题。不过我们不知道这个问题为什么会产生,也不能指望MAT告诉我们。这个问题,如阿加莎·克里斯蒂笔下的赫尔克里·波洛所说,得用“泽灰色小细胞”解决……
以上就是探究内存泄露—Part2—分析问题的内容,更多相关内容请关注PHP中文网(www.php.cn)!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

最近不少使用win11系統的小伙伴,發現自己電腦桌面窗口佔用的內存非常的大,同時還出現了比較嚴重的內存洩露,就會導致其他的程序運行卡頓不流暢,針對這個問題,我們應該用戶甚麼方法來解決呢?我們打開電腦的控制面板,點擊選擇電源按鈕的功能,取消勾選啟用快速啟動選項即可,重新啟動電腦就能解決問題呀,也可能是顯示卡驅動程式出現問題了,重新下載驅動程式就好了。記憶體外洩的原因:記憶體洩漏是由於錯誤的記憶體分配導致電腦程式中的資源錯位。當未使用的RAM位置仍未釋放時,就會發生這種情況。不要將內存洩漏與空間洩漏或內存

Go語言中存在函數記憶體洩露,它會導致應用程式記憶體不斷消耗和崩潰。我們可以使用runtime/pprof套件進行偵測,並檢查函數是否意外保留了對不需要資源的參考。要解決記憶體洩露,我們需要找到導致洩露的引用,通常透過檢查函數程式碼和尋找全域變數或閉包引用來實現。

C++是一種強大的程式語言,但同時也是一種需要仔細處理記憶體管理的語言。在使用C++編寫程式時,經常會遇到記憶體管理問題。本文將詳細解析C++中常見的記憶體管理問題,並提供具體的程式碼範例,幫助讀者理解和解決這些問題。一、記憶體洩漏(MemoryLeak)記憶體洩漏指的是程式中動態分配的記憶體沒有被正確釋放,導致記憶體資源的浪費。這是一個常見的問題,尤其是在大型或長時間運

如何處理Linux系統中頻繁出現的記憶體使用率過高和外洩問題在使用Linux系統的過程中,我們有時會遇到記憶體使用率過高和記憶體外洩的問題。這些問題會導致系統運作緩慢、應用程式崩潰甚至系統崩潰。本文將探討如何解決這些問題。首先,讓我們了解一下記憶體使用率過高和記憶體外洩的概念。記憶體使用率過高記憶體使用率過高意味著系統中的可用記憶體非常少,而大部分記憶體都在使用中。當記憶體使用

PHP記憶體外洩是指應用程式分配記憶體後未能釋放,導致伺服器可用記憶體減少和效能下降。原因包括循環引用、全域變數、靜態變數和擴充。檢測方法有Xdebug、Valgrind和PHPUnitMockObjects。解決步驟為:識別洩漏源、修復洩漏、測試和監控。實戰舉例說明了循環引用導致的記憶體洩露,以及透過析構函數打破循環引用以解決問題的具體方法。

Java中記憶體管理涉及垃圾收集,但仍可能出現問題。常見問題包括記憶體洩漏和記憶體碎片。記憶體洩漏是由於物件持有不再需要的引用,可用透過避免循環引用、使用弱引用和限定變數範圍來解決。記憶體碎片是由於頻繁分配和釋放導致,可用透過使用記憶體池、大物件池和壓縮垃圾收集來解決。例如,使用弱引用可以處理記憶體洩漏問題,確保垃圾收集器在不再需要時回收物件。

Golang是一種快速、高效的開發語言,以其強大的並發能力和內建的垃圾回收機製而受到廣泛的歡迎。然而,即使在使用Golang進行開發時,仍然有可能遇到記憶體外洩的問題。本文將介紹一些常見的Golang開發注意事項,以幫助開發者避免記憶體外洩問題。避免循環引用循環引用是Golang中常見的記憶體外洩問題之一。當兩個物件相互引用時,如果沒有適時地釋放這些物件的引用,就

Go語言作為一種快速、高效、易於使用的程式語言,越來越受到開發者的青睞。然而,就像任何一種程式語言一樣,Go語言開發也存在一些潛在的風險,如果不加以注意和處理,可能會導致程式碼品質下降,甚至產生嚴重的後果。本文將探討Go語言開發中的一些潛在風險,並結合具體的程式碼範例進行分析和討論。 1.並發處理的陷阱Go語言天生支持並發編程,透過goroutine和chann
