6

問題の説明

Javaサーバーアプリケーションを実行してしばらくすると、SolarisでOracleJava仮想マシンの奇妙な動作が発生します。通常、jvmhs_err_pid.logファイルのクラッシュが発生すると、作成されます(場所は、-XX:ErrorFileここで説明されているようにjvm paramterによって決定されます:hs_err_pidファイルの作成を抑制するにはどうすればよいですか?

しかし、私の場合、ファイルは作成されておらず、残っているのはcoreコアダンプファイルだけでした。

標準のSolarisツールを使用pstackpflagsて、ファイルからクラッシュに関する詳細情報(以下に含まれています)を収集することができましたcore

試行されたソリューション

  • hs_err_pid.logファイルシステム全体ですべてのファイルを検索しようとしましたが、何も見つかりませんでした(アプリケーションの作業ディレクトリの外でも)。すなわち:

    find / -name "hs_err_pid*"

  • jvmに関連するjvmのバグを見つけようとしましたが、この場合に似た興味深いものは見つかりませんでした。

  • 問題は次のようになります。JavaVM:1.6.0_17と1.6.0_18の両方で再現可能なSIGSEGV、レポート方法 hs_err_pid.logしかし、ファイルが欠落していて、もちろんOSプラットフォームが異なるため、これを確認することはできません。
  • (編集)Javaコアダンプの質問を分析するためのツールへの回答の1つで提案されているように、Eclipse MATをcore使用してファイルからヒープダンプを抽出し、分析しました。jmapリークが見つかりました(コアダンプの時点で、HashMapに追加された要素、クレンジングされることはありません、1,4 M要素)。hs_err_pid.logただし、これはファイルが生成されなかった理由やjvmがクラッシュした理由を説明していません。
  • (EDIT2) Darryl Milesによって提案されたように、-Xmxの制限がチェックされました(テストには、オブジェクトを無期限に追加するコードが含まれていましたLinkedList):
    • java -Xmx1444m Test結果はjava.lang.OutOfMemoryError: Java heap space
    • java -Xmx2048m Test結果はjava.lang.OutOfMemoryError: Java heap space
    • java -Xmx3600m Testコアダンプの結果。

質問

誰かがjvmで同様の問題を経験し、そのような場合に実際に何が起こったのかを見つける方法(つまり、コアがjvmからダンプされ、hs_err_pid.logファイルが作成されない場合)を経験したことがありますか?

これを解決するためのヒントやポインタは非常に役立ちます。

抽出されたフラグ

# pflags core
...
/2139095:      flags = DETACH
    sigmask = 0xfffffeff,0x0000ffff  cursig = SIGSEGV

抽出されたスタック

# pstack core
...
-----------------  lwp# 2139095 / thread# 2139095  --------------------
 fb208c3e ???????? (f25daee0, f25daec8, 74233960, 776e3caa, 74233998, 776e64f0)
 fb20308d ???????? (0, 1, f25db030, f25daee0, f25daec8, 7423399c)
 fb20308d ???????? (0, 0, 50, f25da798, f25daec8, f25daec8)
 fb20308d ???????? (0, 0, 50, f25da798, 8561cbb8, f25da988)
 fb203403 ???????? (f25da988, 74233a48, 787edef5, 74233a74, 787ee8a0, 0)
 fb20308d ???????? (0, f25da988, 74233a78, 76e2facf, 74233aa0, 76e78f70)
 fb203569 ???????? (f25da9b0, 8b5b400, 8975278, 1f80, fecd6000, 1)
 fb200347 ???????? (74233af0, 74233d48, a, 76e2fae0, fb208f60, 74233c58)
 fe6f4b0b __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (74233d44, 74233bc8, 74233c54, 8b5b400) + 1a3
 fe6f4db3 __1cCosUos_exception_wrapper6FpFpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v2468_v_ (fe6f4968, 74233d44, 74233bc8, 74233c54, 8b5b4
00) + 27
 fe6f4deb __1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (74233d44, 8975278, 74233c54, 8b5b400) + 2f
 fe76826d __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_nMsymbolHandle_4pnRJavaCallArguments_pnGThread__v_ (74233d44, 897526c, fed2d464, fed2d6d0, 7
4233c54, 8b5b400) + c1
 fe76f4fa __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_nMsymbolHandle_5pnGThread__v_ (74233d44, 8975268, 897526c, fed2d464, fed2d6d0, 8b5b
400) + 7e
 fe7805f6 __1cMthread_entry6FpnKJavaThread_pnGThread__v_ (8b5b400, 8b5b400) + d2
 fe77cbe4 __1cKJavaThreadRthread_main_inner6M_v_ (8b5b400) + 4c
 fe77cb8e __1cKJavaThreadDrun6M_v_ (8b5b400) + 182
 feadbd59 java_start (8b5b400) + f9
 feed59a9 _thr_setup (745c5200) + 4e
 feed5c90 _lwp_start (745c5200, 0, 0, 74233ff8, feed5c90, 745c5200)

システムインフォメーション:

# uname -a
SunOS xxxx 5.10 Generic_137138-09 i86pc i386 i86pc
# java -version
java version "1.6.0_11"
Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Server VM (build 11.0-b16, mixed mode)
# ulimit -a
time(seconds) unlimited
file(blocks) unlimited
data(kbytes) unlimited
stack(kbytes) 10240
coredump(blocks) unlimited
nofiles(descriptors) 256
memory(kbytes) unlimited

使用されるjvm引数:

java -Xms1024M -Xmx2048M -verbose:gc -Xloggc:logs/gc.log -server com.example.MyApplication

不足している情報を見つけた場合はコメントしてください。追加しようと思います。

4

2 に答える 2

3

上記の私のコメントによると。-Xmx値を高く設定しすぎると、この問題が32ビットアドレス空間で使用可能なヒープを使い果たしていると思われます。これにより、JVMが制限をポリシングする前に(制御されたOutOfMemoryExceptionメカニズムを使用して)、カーネルが制限をポリシングするように強制されました(新しいメモリの要求を拒否することによって)。残念ながら、そのプラットフォームから何が期待されるかを知るためのIntelSolarisの詳細はわかりません。

ただし、Windowsの一般的なルールとして、最大-Xmxは1800Mであり、作成する追加のアプリケーションスレッドごとに16Mずつ減らすことができます。各スレッドにはスタックスペース(ネイティブスタックとJavaスタックの両方)、およびスレッドローカルストレージなどの他のスレッドごとのアカウンティングが必要なため、この計算の結果から、JavaVMの実際に使用可能なヒープスペースの概算が得られます。オペレーティングシステムが2G/2Gスプリット(ユーザー/カーネル)を使用する32ビットビットプロセス。

WinXP以降では、カーネルの/ 3Gスイッチを使用してより高い分割(3G / 1Gユーザー/カーネル)を取得できます。Linuxには/ proc / <pid> / mapファイルがあり、プロセスアドレスを正確に確認できます。スペースは特定のプロセスからレイアウトされます(このアプリケーションを実行している場合は、[ヒープ]が成長して、DSOからの.text / .rodata / .data /etc...に使用される共有ファイルマッピングを満たすように時間をかけて監視できます。その結果、カーネルはヒープを拡張する要求を拒否します。

使用するアドレス空間が非常に多く、ヒープが他のマッピングと一致する前に物理メモリと仮想(スワップ)メモリが不足するため、この問題は64ビットで解消されます。

Solarisの「truss」は、コアダンプの直前にエラーコードを返すbrk/sbrkシステムコールを表示すると思います。標準のネイティブライブラリの一部は、新しいメモリの要求からのリターンコードをチェックしないようにコーディングされているため、クラッシュが予想されます。

于 2011-10-07T20:25:31.380 に答える
3

6.0_11 はかなり古く、最近の経験がないので、そこにアップグレードすることを強くお勧めします...

ただし、ネイティブ コードの stackoverflow ではクラッシュ ダンプが発生しない場合があります。つまり、スタックが非常に少ないネイティブ関数 (FileOutputStream の書き込みなど、ソケットは同じ impl を使用します) を呼び出します。そのため、JVM がファイルを書き込もうとしても、十分なスタックがなく、書き込みコードもクラッシュします。2 番目の stackoverflow は、プロセスを救済するだけです。

実稼働システムで同様のケース (ファイルが作成されていない) があり、それを追跡するのはうまくいきませんでしたが、上記はその理由を説明しています。

于 2011-10-04T23:42:27.333 に答える