web-dev-qa-db-ja.com

Javaブロッキングの問題:JVMが多くの異なるクラス/メソッドのスレッドをブロックするのはなぜですか?

更新:これはメモリの問題のようです。 3.8 Gb Hprofファイルは、この「ブロッキング」が発生したときにJVMがヒープをダンプしていたことを示していました。運用チームは、サイトが応答していないことを確認し、スタックトレースを取得してから、インスタンスをシャットダウンしました。ヒープダンプが終了する前にサイトをシャットダウンしたと思います。ログにはnoエラー/例外/問題の証拠がありました-おそらく、JVMがエラーメッセージを生成する前に強制終了されたためです。

元の質問最近、アプリケーションが(エンドユーザーに)ハングするように見える状況がありました。アプリケーションを再起動する前にスタックトレースを取得しましたが、驚くべき結果がいくつか見つかりました。527スレッドのうち、463スレッドの状態がBLOCKEDでした。

過去過去には、ブロックされたスレッドには通常この問題がありました:1)いくつかの明らかなボトルネック:例:他のスレッドが待機する原因となったデータベースレコードロックまたはファイルシステムロックの問題。 2)ブロックされたすべてのスレッドは、同じクラス/メソッドでブロックされます(jdbcまたはファイルシステムのクラスなど)

異常なデータこの場合、アプリケーションクラス(jdbcおよびlucene呼び出しを含む)に加えて、jvm内部クラス、jbossクラス、log4jなどを含むすべての種類のクラス/メソッドがブロックされているのがわかります。

質問 JVMがlog4j.Hierarchy.getLogger、Java.lang.reflect.Constructor.newInstanceをブロックする原因は何ですか?明らかに、一部のリソースは「不足しています」が、どのリソースですか?

ありがとう

意志

スタックトレースの抜粋

http-0.0.0.0-80-417" daemon prio=6 tid=0x000000000f6f1800 nid=0x1a00 waiting for monitor entry [0x000000002dd5d000]
   Java.lang.Thread.State: BLOCKED (on object monitor)
                at Sun.reflect.GeneratedConstructorAccessor68.newInstance(Unknown Source)
                at Sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.Java:27)
                at Java.lang.reflect.Constructor.newInstance(Constructor.Java:513)
                at Java.lang.Class.newInstance0(Class.Java:355)
                at Java.lang.Class.newInstance(Class.Java:308)
                at org.jboss.ejb.Container.createBeanClassInstance(Container.Java:630)

http-0.0.0.0-80-451" daemon prio=6 tid=0x000000000f184800 nid=0x14d4 waiting for monitor entry [0x000000003843d000]
   Java.lang.Thread.State: BLOCKED (on object monitor)
                at Java.lang.Class.getDeclaredMethods0(Native Method)
                at Java.lang.Class.privateGetDeclaredMethods(Class.Java:2427)
                at Java.lang.Class.getMethod0(Class.Java:2670)

"http-0.0.0.0-80-449" daemon prio=6 tid=0x000000000f17d000 nid=0x2240 waiting for monitor entry [0x000000002fa5f000]
   Java.lang.Thread.State: BLOCKED (on object monitor)
                at org.Apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.register(Http11Protocol.Java:638)
                - waiting to lock <0x00000007067515e8> (a org.Apache.coyote.http11.Http11Protocol$Http11ConnectionHandler)
                at org.Apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.createProcessor(Http11Protocol.Java:630)


"http-0.0.0.0-80-439" daemon prio=6 tid=0x000000000f701800 nid=0x1ed8 waiting for monitor entry [0x000000002f35b000]
   Java.lang.Thread.State: BLOCKED (on object monitor)
                at org.Apache.log4j.Hierarchy.getLogger(Hierarchy.Java:261)
                at org.Apache.log4j.Hierarchy.getLogger(Hierarchy.Java:242)
                at org.Apache.log4j.LogManager.getLogger(LogManager.Java:198)
18
user331465

これらは、収集された証拠に応じて、私が試してみる順序で大まかにリストされています。

  • GCの動作を見たことがありますか?あなたは記憶のプレッシャーにさらされていますか?その結果、newInstance()および上記の他のいくつかがブロックされる可能性があります。 VM with -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -verbose:gcを実行し、出力をログに記録します。障害/ロックアップの時間の近くに過剰なGC時間が表示されていますか?
    • 条件繰り返し可能ですか?その場合は、JVM(-Xmx)でヒープサイズを変えてみて、動作が大幅に変わるかどうかを確認してください。その場合は、メモリリークを探すか、アプリのヒープのサイズを適切に設定してください。
    • 前の方法が難しく、必要なときにOutOfMemoryErrorが得られない場合は、GCチューナブルを調整できます... JDK6.0 XXオプション を参照してください。 、または JDK6.0 GCチューニングホワイトペーパー 。特に-XX:+UseGCOverheadLimit-XX:+GCTimeLimitおよび関連するオプションを見てください。 (これらは十分に文書化されていませんが、役立つ場合があることに注意してください...)
  • デッドロックがある可能性がありますか?スタックトレースの抜粋だけでは、ここで判断することはできません。スレッドがブロックされているモニター状態の中からサイクルを探します(スレッドが保持しているものと比較して)。 jconsoleがあなたのためにこれを行うことができると私は信じています...( うん、スレッドタブの下で、「デッドロックを検出する」
  • いくつかの繰り返されたスタックトレースを実行して、何が変化するのか、何が変わらないのかを探してください...
  • フォレンジックを実行します...「BLOCKED」と表示されているスタックエントリごとに、コードの特定の行を調べて、そこにモニターがあるかどうかを確認します。実際のモニターの取得がある場合は、制限されているリソースを特定するのはかなり簡単です。ただし、一部のスレッドは、透過的に使用可能なモニターがないとブロックされて表示される場合があります。これらは注意が必要です...
17
andersoj