探究内存泄露—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 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











最近、win11 システムを使用している多くの友人が、コンピューターのデスクトップ ウィンドウが占有しているメモリが非常に大きく、深刻なメモリ リークが発生し、他のプログラムの動作がスムーズにいかなくなっていることに気付きました。解決しますか?コンピューターのコントロール パネルを開き、電源ボタンの機能をクリックして選択し、高速スタートアップを有効にするオプションのチェックを外します。コンピューターを再起動すると問題が解決します。グラフィック カード ドライバーにも問題がある可能性があります。再起動するだけです。ドライバーをダウンロードします。メモリ リークの原因: メモリ リークは、メモリの割り当てが正しくないため、コンピュータ プログラム内のリソースが正しく配置されていないことが原因で発生します。これは、未使用の RAM の場所がまだ解放されていない場合に発生します。メモリ リークをスペース リークまたはメモリ リークと混同しないでください。

Go 言語には関数のメモリ リークがあり、アプリケーションがメモリを継続的に消費してクラッシュする原因となります。 runtime/pprof パッケージを検出に使用し、関数が不要なリソースへの参照を誤って保持していないかどうかを確認できます。メモリ リークを解決するには、通常は関数コードを検査し、グローバル変数またはクロージャ参照を探すことによって、リークの原因となった参照を見つける必要があります。

C++ は強力なプログラミング言語ですが、メモリ管理には注意が必要な言語でもあります。 C++ でプログラムを作成する場合、メモリ管理の問題がよく発生します。この記事では、C++ における一般的なメモリ管理の問題を詳細に分析し、読者がこれらの問題を理解し、解決できるように具体的なコード例を示します。 1. メモリ リーク (MemoryLeak) メモリ リークとは、プログラム内で動的に割り当てられたメモリが正しく解放されず、メモリ リソースが無駄に消費されることを意味します。これは、特に大規模な実行や長期実行の場合によくある問題です。

PHP メモリ リークは、アプリケーションがメモリを割り当て、解放に失敗すると発生し、その結果、サーバーの利用可能なメモリが減少し、パフォーマンスが低下します。原因には、循環参照、グローバル変数、静的変数、展開などが含まれます。検出方法には、Xdebug、Valgrind、PHPUnitMockObjects が含まれます。解決手順は、漏れの原因を特定し、漏れを修正し、テストし、監視することです。実際の例では、循環参照によって引き起こされるメモリ リークと、デストラクターを通じて循環参照を解除することで問題を解決する具体的な方法を示します。

Linux システムで頻繁に発生するメモリ使用量の増加とメモリ リークの問題に対処する方法 Linux システムを使用する過程で、メモリ使用量の増加とメモリ リークの問題が発生することがあります。これらの問題は、システムの速度低下、アプリケーションのクラッシュ、さらにはシステムのクラッシュを引き起こす可能性があります。この記事では、これらの問題を解決する方法について説明します。まず、高メモリ使用量とメモリ リークの概念を理解しましょう。高いメモリ使用量 高いメモリ使用量は、システムで利用可能なメモリが非常に少なく、メモリの大部分が使用されていることを意味します。メモリを使用する場合

Java のメモリ管理にはガベージ コレクションが含まれますが、それでも問題が発生する可能性があります。一般的な問題には、メモリ リークやメモリの断片化などがあります。メモリ リークは、オブジェクトが不要になった参照を保持することによって発生します。これは、循環参照を回避し、弱い参照を使用し、変数のスコープを制限することで解決できます。メモリの断片化は、頻繁な割り当てと割り当て解除によって発生し、メモリ プール、ラージ オブジェクト プール、およびコンパクト ガベージ コレクションを使用することで解決できます。たとえば、弱い参照を使用すると、メモリ リークを処理し、オブジェクトが不要になったときにガベージ コレクターが確実にオブジェクトを再利用できるようになります。

Golang は高速かつ効率的な開発言語であり、強力な同時実行機能と組み込みのガベージ コレクション メカニズムで広く普及しています。ただし、Golang で開発している場合でも、メモリ リークが発生する可能性はあります。この記事では、開発者がメモリ リークの問題を回避できるように、Golang 開発における一般的な考慮事項をいくつか紹介します。循環参照を避ける 循環参照は、Golang でよくあるメモリ リークの問題の 1 つです。 2 つのオブジェクトが相互に参照する場合、これらのオブジェクトへの参照が適時に解放されないと、

Go 言語は、高速で効率的で使いやすいプログラミング言語として、開発者の間でますます好まれています。ただし、他のプログラミング言語と同様に、Go 言語の開発にも潜在的なリスクがいくつかあり、注意を払って対処しないと、コードの品質の低下や重大な結果につながる可能性があります。この記事では、Go 言語開発におけるいくつかの潜在的なリスクを調査し、具体的なコード例を使用して分析し、説明します。 1. 同時処理の罠 Go 言語は本質的に goroutine と chann による同時プログラミングをサポートしています。
