この記事では、JVM スレッド スタックを分析する方法と、スタック情報から問題の根本原因を見つける方法を説明します。スレッドスタック解析技術は、Java EE製品サポートエンジニアが必ず習得すべき技術だと私は考えています。スレッド スタックに保存される情報は通常、想像をはるかに超えており、この情報を仕事で有効に活用できます。
私の目標は、過去十数年にわたってスレッド分析で蓄積した知識と経験を共有することです。この知識と経験は、JVM のさまざまなバージョンとさまざまなベンダーの JVM ベンダーの詳細な分析を通じて得られたものであり、その過程で、多数の一般的な問題のテンプレートもまとめました。
それでは、この記事をブックマークしてください。今後数週間にわたってこのシリーズの特別記事をお届けします。このスレッド分析トレーニング プランを同僚や友人と共有してください。
それはいいですね、スレッド スタック分析スキルを向上させる必要があります...しかしどこから始めればよいでしょうか?
私のアドバイスは、このスレッド分析トレーニング プログラムを受講することです。今回取り上げる研修内容は以下の通りです。同時に、私が扱った実際のケースも共有して、学び、理解できるようにします。
1) スレッド スタックの概要と基礎知識
2) スレッド スタックの生成原理と関連ツール
3) さまざまな JVM でのスレッド スタックの形式の違い (Sun HotSpot、IBM JRE、Oracal JRockit)
4) スレッドの概要スタックログと解析手法
5) スレッドスタック解析と関連技術
6) 一般的な問題テンプレート (スレッド競合、デッドロック、IO コールハング、ガベージコレクション/OutOfMemoryError 問題、無限ループなど)
7) スレッドスタック問題の例 解析
この一連のトレーニングが皆様のお役に立つことを願っておりますので、引き続き毎週の記事更新にご注目ください。
しかし、学習プロセス中に質問がある場合、または記事の内容を理解できない場合はどうすればよいでしょうか?
心配しないで、私をあなたの指導者だと思ってください。スレッド スタックについて質問がある場合は、私に相談してください (問題が低すぎない限り)。私にご連絡いただくには、次の方法のいずれかをお気軽に選択してください:
1) この記事のすぐ下にコメントを残してください (申し訳ない場合は、匿名のままでも構いません)
2) スレッド スタック データを根本原因分析フォーラム
3) 私のアドレスは @phcharbonneau@hotmail.com にメールを送信してください
当社の製品で発生した問題の分析を手伝ってもらえますか?
もちろん、ご希望であれば、スタックのライブデータを電子メールまたは根本原因分析フォーラム経由で送信していただけます。実践的な問題に対処することは、スキルを学び向上させるための最良の方法です。
皆さんがこのトレーニングを気に入っていただけることを心から願っています。高品質の資料を提供し、さまざまなご質問にお答えできるよう最善を尽くします。
スレッドスタック解析技術と問題パターンを紹介する前に、まず基本的な内容をお伝えしなければなりません。そのため、この投稿では、誰もが JVM、ミドルウェア、および Java EE コンテナ間の相互作用をよりよく理解できるように、最初に最も基本的な内容を説明します。
Java VM の概要
Java 仮想マシンは Java EE プラットフォームの基盤です。ミドルウェアとアプリケーションがデプロイされ、実行される場所です。
JVM は、ミドルウェア ソフトウェアと Java/Java EE プログラムに次のものを提供します:
– (バイナリ形式) Java/Java EE プログラム実行環境
– 一部のプログラム機能とツール (IO インフラストラクチャ、データ構造、スレッド管理、セキュリティ、監視など)
– ガベージ コレクションによる動的なメモリ割り当てと管理
JVM は多くのオペレーティング システム (Solaris、AIX、Windows など) 上に常駐でき、物理サーバーの構成に応じて、1 つの
JVM とミドルウェア間の相互作用
次の図は、JVM、ミドルウェア、アプリケーションのプログラム間の高レベルの相互作用モデルを示しています。
この図は、JVM、ミドルウェア、アプリケーション ソフトウェア間の単純かつ典型的な相互作用を示しています。ご覧のとおり、標準 Java EE アプリケーションのスレッドの割り当ては、ミドルウェア カーネルと JVM の間で行われます。 (もちろん例外もあります。アプリケーションは API を直接呼び出してスレッドを作成できます。これは一般的ではないため、使用中に特別な注意が必要です)
同時に、一部のスレッドは JVM によって内部的に管理されることにも注意してください。典型的な例はガベージ コレクション スレッドです。これは、並列ガベージ コレクション処理を実行するために JVM によって内部的に使用されます。
ほとんどのスレッド割り当ては Java EE コンテナによって行われるため、スレッド スタック トレースを理解して認識できること、またスレッド スタック データからスレッド スタック トレースを識別できることが重要です。これにより、スレッドの種類をすばやく知ることができます。 Java EE コンテナが実行しているリクエスト
スレッド ダンプ スタックの分析の観点から、JVM によって検出されたスレッド プール間の違いを理解し、リクエストのタイプを識別することができます。
最後のセクションでは、HotSop VM の JVM スレッド スタックの概要と、遭遇するさまざまなスレッドについて説明します。IBM VM スレッド スタック フォームの詳細については、4 番目のセクションで説明します。
この記事のスレッド スタックの例は、根本原因分析フォーラムから入手できることに注意してください。
JVM スレッド スタックとは何ですか?
JVM スレッド スタックは、次の情報を提供します。作成されたすべての Java スレッドの完全なリストが表示されます。
検出された各 Java スレッドは次の情報を提供します:
– スレッド識別子を識別するためにミドルウェア ベンダーによってよく使用されるスレッドの名前。通常、割り当てられたスレッドも表示されます。プール名とステータス (実行中、ブロックされているなど) - スレッドのタイプと優先順位 (例: daemon prio=3) ** ミドルウェア プログラムは通常、バックグラウンド デーモンの形式でスレッドを作成します。これは、これらのスレッドがバックグラウンドで実行されていることを意味します。 ; Java EE アプリケーションなどにサービスを提供します** - Java スレッド ID、例: tid=0x000000011e52a800 ** これは lang.Thread.getId() によって取得されることがよくあります。自己増加する長整数 1..n** - ネイティブ スレッド ID、例: nid=0x251c**、重要なのはネイティブ スレッド ID であるため、どのスレッドがほとんどのスレッドを使用しているかなどの関連情報を取得できます。オペレーティング システムの観点から見た JVM の CPU 時間。 **
— Java スレッドのステータスと詳細: モニター エントリ [0xfffffffea5afb000] を待機中 java.lang.Thread.State: BLOCKED (オブジェクト モニター上)
**スレッドのステータスと現在のブロックの考えられる理由をすぐに理解します** —Java スレッド スタック トレース。これは、スレッド スタック内で見つかる最も重要なデータです。 Java スタック トレースによって、必要な情報の 90% が演習の後半で学習するさまざまな種類の問題の根本原因が提供されるため、分析に最も時間がかかります。Heap PSYoungGen total 466944K, used 178734K [0xffffffff45c00000, 0xffffffff70800000, 0xffffffff70800000) eden space 233472K, 76% used [0xffffffff45c00000,0xffffffff50ab7c50,0xffffffff54000000) from space 233472K, 0% used [0xffffffff62400000,0xffffffff62400000,0xffffffff70800000) to space 233472K, 0% used [0xffffffff54000000,0xffffffff54000000,0xffffffff62400000) PSOldGen total 1400832K, used 1400831K [0xfffffffef0400000, 0xffffffff45c00000, 0xffffffff45c00000) object space 1400832K, 99% used [0xfffffffef0400000,0xffffffff45bfffb8,0xffffffff45c00000) PSPermGen total 262144K, used 248475K [0xfffffffed0400000, 0xfffffffee0400000, 0xfffffffef0400000) object space 262144K, 94% used [0xfffffffed0400000,0xfffffffedf6a6f08,0xfffffffee0400000)
よりわかりやすくするために、HotSpot VM 上のスレッド スタック情報とスレッド プールを詳細に解体した図を示します。以下の図:
上の図からわかるように、スレッド スタックは多くの異なる部分で構成されています。この情報はすべて問題分析にとって重要ですが、さまざまな問題パターンを分析するには別の部分が使用されます (問題パターンは後の記事でシミュレートされ、実証されます)。
この分析例を通して、詳細を説明します。 HoteSpot のスレッド スタック情報のさまざまなコンポーネント:# Full thread dump标示符
「フル スレッド ダンプ」は世界的に一意のキーワードであり、ミドルウェアおよびスタンドアロン バージョンの Java のスレッド スタック情報の出力ログで見つけることができます (たとえば、UNIX の場合: kill -3
完全なスレッド ダンプ Java HotSpot(TM) 64 ビット サーバー VM (20.0-b11 混合モード):
このスレッド スタックの例では、WebLogic が使用しているミドルウェアです。 Weblogic 9.2 以降、「'weblogic.kernel.Default (self-tuning)」で一意に識別される自己管理のスレッド プールが使用されます
"[STANDBY] ExecuteThread: '414' for queue: 'weblogic.kernel.Default (self-tuning)'" daemon prio=3 tid=0x000000010916a800 nid=0x2613 in Object.wait() [0xfffffffe9edff000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0xffffffff27d44de0> (a weblogic.work.ExecuteThread) at java.lang.Object.wait(Object.java:485) at weblogic.work.ExecuteThread.waitForRequest(ExecuteThread.java:160) - locked <0xffffffff27d44de0> (a weblogic.work.ExecuteThread) at weblogic.work.ExecuteThread.run(ExecuteThread.java:181)# HotSpot VM thread
これは Hotspot VM Internal によって管理されるスレッドです内部ネイティブ操作を実行するために使用されるスレッド。一般に、(関連するスレッド スタックと prstat またはネイティブ スレッド ID を介して) CPU 使用率が高くなっていない限り、これについてあまり心配する必要はありません。
"VM Periodic Task Thread" prio=3 tid=0x0000000101238800 nid=0x19 waiting on condition# HotSpot GC スレッド
並列 GC に HotSpot を使用する場合 (一般的)。 HotSpot VM がデフォルトで作成される場合、または各 JVM が特定の ID で GC スレッドを管理する場合、これらの GC スレッドにより、VM は定期的な GC を並行して実行できるようになります。全体的な GC 時間の短縮には同時に、CPU 使用時間の増加が伴います。
"GC task thread#0 (ParallelGC)" prio=3 tid=0x0000000100120000 nid=0x3 runnable "GC task thread#1 (ParallelGC)" prio=3 tid=0x0000000100131000 nid=0x4 runnable ………………………………………………………………………………………………………………………………………………………………
这事非常关键的数据,因为当你遇到跟GC有关的问题,诸如过度GC、内存泄露等问题是,你将可以利用这些线程的原生Id值关联的操作系统或者Java线程,进而发现任何对CPI时间的高占用. 未来的文章你将会了解到如何识别并诊断这样的问题.
# JNI 全局引用计数
JNI (Java 本地接口)的全局引用就是从本地代码到由Java垃圾收集器管理的Java对象的基本的对象引用. 它的角色就是阻止对仍然在被本地代码使用,但是技术上已经不是Java代码中的“活动的”引用了的对象的垃圾收集.
同时为了侦测JNI相关的泄露而留意JNI引用也很重要. 如果你的程序直接使用了JNI,或者像监听器这样的第三方工具,就容易造成本地的内存泄露.
JNI global references: 1925
# Java 堆栈使用视图
这些数据被添加回了 JDK 1 .6 ,向你提供有关Hotspot堆栈的一个简短而快速的视图. 我发现它在当我处理带有过高CPU占用的GC相关的问题时非常有用,你可以在一个单独的快照中同时看到线程堆栈以及Java堆的信息,让你当时就可以在一个特定的Java堆内存空间中解析(或者排除)出任何的关键点. 你如在我们的示例线程堆栈中所见,Java 的堆 OldGen 超出了最大值!
Heap PSYoungGen total 466944K, used 178734K [0xffffffff45c00000, 0xffffffff70800000, 0xffffffff70800000) eden space 233472K, 76% used [0xffffffff45c00000,0xffffffff50ab7c50,0xffffffff54000000) from space 233472K, 0% used [0xffffffff62400000,0xffffffff62400000,0xffffffff70800000) to space 233472K, 0% used [0xffffffff54000000,0xffffffff54000000,0xffffffff62400000) PSOldGen total 1400832K, used 1400831K [0xfffffffef0400000, 0xffffffff45c00000, 0xffffffff45c00000) object space 1400832K, 99% used [0xfffffffef0400000,0xffffffff45bfffb8,0xffffffff45c00000) PSPermGen total 262144K, used 248475K [0xfffffffed0400000, 0xfffffffee0400000, 0xfffffffef0400000) object space 262144K, 94% used [0xfffffffed0400000,0xfffffffedf6a6f08,0xfffffffee040000
更多Java のスレッド スタックの詳細な JVM 分析相关文章请关注PHP中文网!