5

Fedora Core 6 と JDK 1.5.0_08 で実行されているアプリケーションに問題があります。

ある程度の稼働時間 (通常は数日) の後、スレッドはネイティブ メソッドでスタックし始めます。

スレッドは次のようにロックされています。

"pool-2-thread-2571" prio=1 tid=0x08dd0b28 nid=0x319e waiting for monitor entry [0xb91fe000..0xb91ff7d4]
at java.lang.Class.getDeclaredConstructors0(Native Method)

また

"pool-2-thread-2547" prio=1 tid=0x75641620 nid=0x1745 waiting for monitor entry [0xbc7fe000..0xbc7ff554]
at sun.misc.Unsafe.defineClass(Native Method)

私にとって特に不可解なのは、これです:

"HealthMonitor-10" daemon prio=1 tid=0x0868d1c0 nid=0x2b72 waiting for monitor entry [0xbe5ff000..0xbe5ff4d4]
at java.lang.Thread.dumpThreads(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:1383)

VM が再起動されるまで、スレッドは停止したままになります。

ここで何が起こっているのか、何がネイティブメソッドをブロックさせているのか、誰か教えてもらえますか? 各スタック スレッドの上部にあるモニター エントリ アドレス範囲は異なります。このモニターを保持しているものを特定するにはどうすればよいですか?

提案やアドバイスをいただければ幸いです。

ありがとう、デビッド

4

5 に答える 5

4

私の最初の疑いは、何らかの種類のクラスローダーのデッドロックが発生していることです。クラス情報は、最初にロードされたスレッドだけでなく、VM全体で利用できるようになるため、クラスのロードをあるレベルで同期する必要があると思います。

スタック上のメソッドがネイティブ メソッドであるという事実は、クラス ローディング メカニズムの一部がたまたまそのように実装されているため、まったくの偶然のようです。

クラスローディングに関して何が起こっているのかをさらに調査します。おそらく、一部のスレッドがクラスローダーを使用して、低速/利用できないネットワークの場所からクラスをロードするため、非常に長い間ブロックされ、クラスをロードしたい他のスレッドにモニターを明け渡すことができません。-verbose:class を使用して JVM を開始したときの出力を調べることは、試してみる価値のあることの 1 つです。

于 2008-09-30T10:50:43.080 に答える
2

I was having similar problems a few months ago and found the jthread(?) utility to be invaluable. You give it the process ID for your Java application and it will dump the entire stack for each thread in your process.

From the output of jthread, I could see one thread was trying to obtain a lock after having entered a monitor and another thread was trying to enter the monitor after obtaining the lock. A recipe for deadlock.

I was also wondering if your application was running into a garbage collection issue. You say it runs for a couple days before it stops like this. How long have you let it sit in the stuck state to see if maybe the GC ever finishes?

于 2008-10-01T05:50:50.283 に答える
1

ネイティブ メソッドが待機しているモニターで、実際に同期しているスレッドを特定できますか? 少なくとも、VM に SIGQUIT (kill -3) を送信したときに VM から取得するスレッド ダンプには、次のようにこの情報が表示されるはずです。

"Thread-0" prio=5 tid=0x0100b060 nid=0x84c000 waiting for monitor entry [0xb0c8a000..0xb0c8ad90]
    at Deadlock$1.run(Deadlock.java:8)
    - waiting to lock <0x255e5b38> (a java.lang.Object)
...
"main" prio=5 tid=0x01001350 nid=0xb0801000 waiting on condition [0xb07ff000..0xb0800148]
    at java.lang.Thread.sleep(Native Method)
    at Deadlock.main(Deadlock.java:21)
- locked <0x255e5b38> (a java.lang.Object)

これまでに投稿したダンプでは、特定のモニターをロックするために実際に待機しているスレッドは見当たりません...

于 2008-10-07T10:19:34.533 に答える
0

たぶん、別のjdkバージョンを使用する必要があります。
「不可解なもの」については、1.5.0_08のバグエントリがあります。メモリリークが報告されています(これが問題に関連しているかどうかはわかりません): http://bugs.sun.com/bugdatabase/view_bug.do?
bug_id = 6469701

また、ソースコードを取得して、1383行目で何が起こっているかを確認することもできます。反対側では、元のエラーが発生した後のスタックダンプである可能性があります。

于 2008-09-01T19:22:39.293 に答える
0

同じ問題に遭遇した後、このスレッドを見つけました-Tomcat 6.0.29を搭載したLinuxで実行されているJDK 1.6.0_23。ただし、これらのビットが関連しているかどうかはわかりません。私が気付いたのは、多くのスレッドが getDeclaredConstructors() ネイティブ メソッドで「スタック」していることを除けば、Java プロセスの CPU が 100% であったことです。したがって、すべての要求スレッドがここでスタックし、CPU が 100% になり、スレッド ダンプにデッドロックが表示されず (他のスレッドが重要なアクティビティを実行していない)、スラッシング ガベージ コレクターのようなにおいがしました。案の定、サーバー ログを確認したところ、多数の OutOfMemory エラーがありました - ヒープ スペースが使い果たされていました。

これがスレッドが毎回ここでスタックする根本的な原因になるとは言えませんが、うまくいけば、ここの情報が他の人が少なくともこれを考えられる原因として除外するのに役立つことを願っています...

于 2011-02-15T15:41:30.270 に答える