2016-08-04 5 views
0

私の上司は、私たちのテスター用のJavaクライアントに「ワンボタンメモリリークチェッカー」を書くことができるかどうかを知りたがっています(プロファイラの下で完全な手動テストスイートを実行する時間を短縮する必要があったので、自動化されたテストスイートを持っています)。 私はそれをWindowsのVSでコンパイルするために少し修正しなければならなかった(私はそれがMacの下でGCC用に作られたと思う)。しかし、私はそれを実行すると、JVMがクラッシュします。Javaネイティブエージェントの* native * stack-traceエラー時の取得方法?

私はネイティブのスタックトレースを取得して、少なくともクラッシュする場所を知りたいのですが、何が起こったのかを知ることができれば、idkの方法を知りたいと思います。私は "デバッグ" DLLをビルドしましたが、スタックトレースはまだ得られません。コンソールでも、JVMによって生成された "hs_err_pidXXXX.log"ファイルでもありません。

私は約15年間でC/C++を行っていません。私はまだコードが何をするかを "推測"することができますが、デバッグの仕方は忘れています(printfのどこでも... ...).JVMでネイティブコードをデバッグする必要はありませんでした。これまでのところ、Googleは役に立たなかった。おそらく間違った言葉を使って検索しています。

+1

読む[この](https://jpassing.com/tag/stacktrace-dbghelp/)または[この](のhttp:// WWW。 codeproject.com/Articles/11132/Walking-the-callstack)。しかし、***ヒープ・ダンプ( 'jmap -dump:file = ')を取得し、** [HeapAnalyzer](https:// www .com/developerworks/community/groups/service/html/communityview?communityUuid = 4544bafe-c7a2-455f-9d43-eb866ea60091)** – rustyx

+0

コール・サイト記録のスタック・トレースの割り振りを目的としていない限り、メモリリークの診断に役立ちます。 – the8472

+0

エージェントが働いていれば、それ以上存在してはならないものが参照される場所を教えてくれます。しかし、私の問題は、それ自体が潜在的なメモリリークとは関係ないクラッシュであるということです。 –

答えて

2

JVMは通常、クラッシュダンプ内にネイティブスタックトレースを報告します。 hs_err_pid.logにスタックトレースがない場合は、通常、読み取り不可能なアドレスを指しているため、JVMはPCレジスタから最後のフレームを取得できませんでした。ネイティブコードがNULL関数ポインタ参照解除する場合

は例えば、これは起こることができます:

void (*func)() = 0; 
func(); 

PCがゼロになります。この場合、およびJVMは、トレースが印刷されません。しかし、呼び出し元のPCはスタックから見つけることができます。なぜなら、戻りアドレスは通常、呼び出しの前にスタックにプッシュされるからです。ここhs_err_pid.logでそれを見つける方法です。

Top of Stack: (sp=0x0000000002e2f438) 
0x0000000002e2f438: 00007ffcf03f1030 00007ffcf041d000 
         ^^^^^^^^^^^^^^^^ 
         the return address (the address after the last valid instruction) 

次にあなたがDynamic librariesセクションでこのアドレスを見つけるとDLLの先頭からのオフセットを計算することができます。

Dynamic libraries: 
... 
0x00007ffcf03f0000 - 0x00007ffcf0426000 C:\Java\Test\crash.dll 
^^^^^^^^^^^^^^^^^^ 
offset = 0x00007ffcf03f1030 - 0x00007ffcf03f0000 = 0x1030 

コード内の特定の機能/命令にoffestをデコードする使用分解(例えば、ビジュアルスタジオのdumpbin)。


クラッシュ時にVisual StudioデバッガをJVMに接続することもできます。これを行うには、-XX:+ShowMessageBoxOnErrorでJavaを実行する必要があります。次のウィンドウは、デバッガを接続することを勧めます:

ShowMessageBoxOnError

+0

hs_err_pid.logの内容が多少異なっているようです(異なるJavaバージョンや32/64ビットの違いのためかもしれません)、アドレスを特定のDLLにマップできませんでした。しかし、-XX:+ ShowMessageBoxOnErrorがトリックでした。残念ながら、エラーはjvm.dllの内部で発生し、Oracleはjvm.pdbを提供していないため、私はあきらめなければなりませんでした(また、私はこのタスクのために "割り当てられた時間"を過ぎていました)。 –