著者:オリジナル教会Javaから転送:https://www.javatang.com/archives/2017/10/26/08572060.html
故障解析とパフォーマンスの最適化シリーズJVM
故障解析とパフォーマンスの最適化1 JVMシリーズ:jstack位置決めスレッドスタック情報
JVMの故障解析および2つのシリーズのパフォーマンスの最適化:jstack生成されたスレッドダンプログ構造解明
3つのJVMの故障解析およびパフォーマンスの最適化シリーズ:コマンドを使用してVM JSTATスレッド分析
JVM上の障害解析やパフォーマンスの最適化シリーズ:jstack生成したスレッドダンプログのスレッド状態
JVMの故障解析と性能の最適化5シリーズ:一般的なスレッドダンプログのケーススタディ
6 JVM故障解析とパフォーマンスの最適化シリーズ:JVMのヒープダンプ使用(ヒープダンプファイル)の生成とのMAT
JVMの故障解析および7のパフォーマンスの最適化シリーズ:ソース・オーバーフローを見つけヒストグラムとドミネーターツリーMATを使用
症状と解決策
ここに対応しているいくつかの一般的な症状の解決策は以下のとおりです。
CPU使用率が、応答が非常に遅い、高いです
よる「Javaのメモリリーク分析一連:jstack位置決めスレッドスタック情報」前記方法において、第1のCPU集約型のプロセスを見つけ、そして、対応するスレッドに移動し、最終的にスタックに対応する情報を分析します。
同時に、繰り返し上記の方法を使用して、どこコードから、問題の原因を見つけるために、分析しました。スレッドは、「VMスレッド」に指摘されている場合、または直接コードから理由を見つけることができない、それは、以下の特定の記事メモリ分析のために必要です。
CPU占有率は高くありませんが、応答が非常に遅いです
次に得るために比べて全体の要求複数のスレッドダンプ実行の過程でBLOCKED
スレッドは、典型的には、I / O、データベースまたはネットワーク接続の場所で停止しているため、スレッドの状態リスト。
フォーカスの概要
スレッドダンプファイルでは、2へのスレッドの状態:ネイティブスレッドステータスとJVMスレッドのステータスは、特定の意味は、以前の記事を参照することができます。以下は、いくつかの共通のスレッドがあるログ解析時の状態を集中する必要があります。
システムスレッド・ステータス・デッドロック
スレッドがデッドロックされている、それは多くのシステムリソースを占有します。
システムスレッドの状態がされて)(モニタエントリのかはObject.waitで待っています
BLOCKED:記事で述べたように、システムのスレッドがクリティカルセクションに入るのを待っていることをこの状態にある場合、状態のJVMスレッドは通常java.lang.Thread.Stateです。
この状態のスレッドの数ならば、それは多数のスレッドをブロックされたグローバルロックであってもよいです。短期的には複数の印刷スレッドダンプ情報場合は、見つかったwaiting for monitor entry
後半傾向はそう、より多くの新しいスレッドという、あまりにも長い時間のための重要なゾーンでいくつかのスレッドを意味する可能性が減少していない、より多くのスレッドの状態を後半にアクセスできない。
システムスレッドの状態がされた状態で待機中
システムスレッドは、他の条件は自分自身を覚ますために起こるのを待っている、または彼がスリープ()メソッドを発行したことをしていることをこの状態にあります。WAITING(パーキング)(起床待ち状態)またはjava.lang.Thread.State:TIMED_WAITING(駐車または睡眠)(時間指定ウェイクアップ条件を待っている)状態JVMスレッドは、一般的にjava.lang.Thread.Stateです。
これらのスレッドは、このようなネットワークリソースやデータベースなどのサードパーティのリソースを、取りに行ったことを示している。この状態では、スレッドの数は、第三者の操作を読めば、長時間待機状態にスレッドが多数で、その結果、応答を取得することはできません。したがって、このシステムは、データベース、ネットワークのボトルネックに記載されているか、読み出し動作時間が長すぎます。
システムスレッドの状態がされてブロックされました
スレッドは、ブロックされた実際の状況に応じて決定する必要がされています。
ケーススタディ
のは、いくつかの例による分解の問題を解決するために取得してみましょう。
java.lang.Thread.State和モニタエントリを待っている:BLOCKED
"DB-Processor-13" daemon prio=5 tid=0x003edf98 nid=0xca waiting for monitor entry [0x000000000825f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at beans.ConnectionPool.getConnection(ConnectionPool.java:102)
- waiting to lock <0xe0375410> (a beans.ConnectionPool)
at beans.cus.ServiceCnt.getTodayCount(ServiceCnt.java:111)
at beans.cus.ServiceCnt.insertCount(ServiceCnt.java:43)
"DB-Processor-14" daemon prio=5 tid=0x003edf98 nid=0xca waiting for monitor entry [0x000000000825f020]
java.lang.Thread.State: BLOCKED (on object monitor)
at beans.ConnectionPool.getConnection(ConnectionPool.java:102)
- waiting to lock <0xe0375410> (a beans.ConnectionPool)
at beans.cus.ServiceCnt.getTodayCount(ServiceCnt.java:111)
at beans.cus.ServiceCnt.insertCount(ServiceCnt.java:43)
"DB-Processor-3" daemon prio=5 tid=0x00928248 nid=0x8b waiting for monitor entry [0x000000000825d080]
java.lang.Thread.State: RUNNABLE
at oracle.jdbc.driver.OracleConnection.isClosed(OracleConnection.java:570)
- waiting to lock <0xe03ba2e0> (a oracle.jdbc.driver.OracleConnection)
at beans.ConnectionPool.getConnection(ConnectionPool.java:112)
- locked <0xe0386580> (a java.util.Vector)
- locked <0xe0375410> (a beans.ConnectionPool)
at beans.cus.Cue_1700c.GetNationList(Cue_1700c.java:66)
at org.apache.jsp.cue_1700c_jsp._jspService(cue_1700c_jsp.java:120)
システムの状態は、スレッド上にあるwaiting for monitor entry
{}クリティカルセクションを入力するために適用するこのスレッドが同期(OBJ)により記載されているが、モニタは、別のスレッドによって状態JVMスレッドを所有OBJ対応するjava.lang.Thread.Stateある:(上でブロックオブジェクトモニタ)、命令のスレッド待ちタイムアウトリソース。
次waiting to lock <0xe0375410>
のために待機しているスレッドの説明0xe0375410
(0xe0375410ロックを取得しようとしている)ロックアドレス、それはログに発見された場合には、多数のスレッドが待っている持って0xe0375410
、それをロックログにロックを獲得したスレッドを見つけるために、この時間の必要性をlocked <0xe0375410>
、あなたがそれをフォローアップすることができますので、上記の例のように、「DB-プロセッサ-14」のスレッドです。データベース操作へのアクセスが原因で、データベース接続のための設定情報を変更する必要性に、あまりにも長い間、この時間を待つようにするので、上記の例です。
2つのスレッドが互いに他のスレッドロックにロックされている場合、このよう原因死锁
次の例のように、現象:
状態で待機和java.lang.Thread.State:TIMED_WAITING
"RMI TCP Connection(idle)" daemon prio=10 tid=0x00007fd50834e800 nid=0x56b2 waiting on condition [0x00007fd4f1a59000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000acd84de8> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:424)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:874)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:945)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:662)
JVMスレッド状態java.lang.Thread.Stateある:TIMED_WAITING(パーキング)、タイミング待ちの状態で説明したスレッドは、スレッド内の駐車手段が吊り下げられています。
waiting on condition
これは、スタックの組み合わせが必要です。<0x00000000acd84de8>(待つために駐車場を java.util.concurrent.SynchronousQueue $ TransferStack) 解析一緒に。まず第一に、このスレッドは間違いなく自分自身に目を覚ますための条件の発生を待っています。第二に、SynchronousQueueないキューが、スレッド間の情報の転送の仕組み、我々はそれがこのスレッドに条件を待っているので、タスクの転送を受け入れるために待機している別のスレッドを持っていなければならない時間にSynchronousQueueに要素を入れたとき。
中にはObject.wait()和java.lang.Thread.State:TIMED_WAITING
"RMI RenewClean-[172.16.5.19:28475]" daemon prio=10 tid=0x0000000041428800 nid=0xb09 in Object.wait() [0x00007f34f4bd0000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000aa672478> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <0x00000000aa672478> (a java.lang.ref.ReferenceQueue$Lock)
at sun.rmi.transport.DGCClient$EndpointEntry$RenewCleanThread.run(DGCClient.java:516)
at java.lang.Thread.run(Thread.java:662)
この場合のJVMスレッド状態がされjava.lang.Thread.State: TIMED_WAITING (on object monitor)
たスレッドが呼び出す記載java.lang.Object.wait(long timeout)
待機状態に入るための方法。
スレッド状態「の設定を待っが」待っているin Object.wait()
スレッドはモニターがクリティカルセクションに入る取得すると、スレッドが条件を満たさないと判断した場合に実行し続け、それはあきらめて、待機()メソッドの呼び出し元のオブジェクト(通常は同期オブジェクト)でありますモニターは、キュー「の設定を待ちます」と入力します。別のスレッドの呼び出しは、(通知)またはオブジェクト上のnotifyAll()メソッド、オブジェクトを取得するために、彼らは競争する機会を得る前にキュースレッド「の設定を待って」が、唯一つのスレッドのモニタ、実行中の状態に戻るときにのみ。
また、注意することが重要で、そのされている最初のロック<0x00000000aa672478>その後、待機ON <0x00000000aa672478>は、そう、次のコードによって実証することができますされています。
static private class Lock { };
private Lock lock = new Lock();
public Reference<? extends T> remove(long timeout) {
synchronized (lock) {
Reference<? extends T> r = reallyPoll();
if (r != null) return r;
for (;;) {
lock.wait(timeout);
r = reallyPoll();
// ……
}
}
线程在执行的过程中,先用 synchronized 获得了这个对象的 Monitor(对应 locked <0x00000000aa672478>),当执行到 lock.wait(timeout);
的时候,线程就放弃了Monitor的所有权,进入 "Wait Set" 队列(对应 waiting on <0x00000000aa672478>)。
前面几篇文章详细说明了如何分析Thread Dump文件,除此之外还可以通过分析JVM堆内存信息来进一步找到问题的原因。
参考资料:
性能分析之-- JAVA Thread Dump 分析综述
三个实例演示 Java Thread Dump 日志分析
如何分析Java虚拟机死锁
各种 Java Thread State 第一分析法则
How to Analyze Java Thread Dumps | 中文版