- PR -

JVMのOutOfMemory時にstack traceを出力したい

1
投稿者投稿内容
kamiyu
会議室デビュー日: 2004/07/12
投稿数: 2
投稿日時: 2004-07-12 18:59
kamiyuと申します。

初めて投稿させて頂きます。
下記の件、ご存知の方がいらっしゃいましたら是非ご教授下さい

現在下記プラットフォームにて複数のアプリケーションを動作させています。
OS: Solaris8
APサーバ: Oracle9iAS(JDK1.3.1_10)

本環境にてjava.lang.OutOfMemoryが発生したので、ヒープメモリのチューニングを実施しました。
チューニングの結果、下記のjava起動コマンドにてJVMを起動しています
java -server -Xmx256MB -Xms256MB -Xss128K -XX:NewSize=84M -XX:MaxNewSize=84M -XX:SurvivorRatio=8 -jar orion.jar
(orion.jarはOracle9iASのJ2EEコンテナインスタンスです)

JVMの確保するヒープメモリを増やしたことで解決したように見た(数ヶ月エラーは発生しませんでした)のですが、再発してしまいましたので、verbosegcオプションでガベージの状況を注視してみましたが原因は特定できませんでした。

そこで、アプリケーション側の調査をしたいと思っています。
java起動時の標準出力やOracle9iASのserver.logにはOutOfMemoryが発生したことを通知しているのですが、下記の通りスタックトレースが出力されません。
 java.lang.OutOfMemoryError
<<no stack trace available>>
これを出力する手段はあるのでしょうか?
(HP-UX上で動作するJDKでは手段が公開されていましたが。。)

また、java起動オプションの-Xrunhprof:heap=〜で、不定期に発生するOutOfMemory時のヒープ情報を取得可能な手段はあるのでしょうか?

何か情報がございましたら是非よろしくお願いいたします。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-07-13 00:43
私が知る限り OutOfMemoryErorr が発生した際のスタックを取得する方法はありません。
あったとしても、メモリリークしている個所で直接 OutOfMemoryError が発生するとは限りませんので意味のある情報はとれないかもしれません。

full GC 後のメモリ使用量が継続的に増加していき OutOfMemoryError になるのであればどこかでオブジェクトを参照しつづけてメモリリークが発生していることになります。
数ヶ月エラーが発生しなかったとのことですので急激に負荷が増加して単純にヒープ不足に陥ったのではないでしょうか?
想定されるだけの負荷をかけて、想定される数だけHTTPセッションが生成されてもヒープが十分に足りるようにチューニングしましょう。

また verbosegc のログは取得済みとのことなので
・侍
http://yusuke.homeip.net/samurai/
や、
・jtune
http://h50146.www5.hp.com/products/software/development/java/tool/jtune/
などで観察してみましょう。

メモリリークが確認されたらプロファイラなどで調査しましょう。
http://h50146.www5.hp.com/products/software/development/java/tool/jmeter/

ヒープ領域が足りているのに OutOfMemoryError が発生しているのであれば Permanent領域が不足している可能性があります。
-XX:MaxPermSize=128m
とか設定すれば解消できるかも。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-07-13 09:59
unibon です。こんにちわ。

引用:

kamiyuさんの書き込み (2004-07-12 18:59) より:
java起動時の標準出力やOracle9iASのserver.logにはOutOfMemoryが発生したことを通知しているのですが、下記の通りスタックトレースが出力されません。
 java.lang.OutOfMemoryError
<<no stack trace available>>
これを出力する手段はあるのでしょうか?
(HP-UX上で動作するJDKでは手段が公開されていましたが。。)


ちなみに、Sun の Java のどれかのバージョンだと、
-Djava.compiler=NONE
などのような起動時の指定をすると、スタックトレースが出せた記憶があります。
なお、たとえ OutOfMemoryError でスタックトレースが出せたとしても、それは単に直前の new した個所を示しているだけであり、そこは直接の原因ではないことが多いです。
それ以前にメモリーリークになっている個所の特定は、別の方法で探る必要がありそうですが、これが難しいです。
kamiyu
会議室デビュー日: 2004/07/12
投稿数: 2
投稿日時: 2004-07-13 16:55
インギさん、unibonさん、ご回答ありがとうございます。

確かにお二人がおっしゃる通り、OutOfMemory発生時のスタックトレースでは、
抜本的な解決を見れないと認識しました。
もしアプリケーションのメモリリークであった場合、、
現在APサーバで動作しているアプリケーションの数(クラス数)がかなり多いため
メモリリーク箇所の特定がかなり難しいのでは、、と悩んでおります。
-verbose:gcを取得した際もab(アパッチベンチ)で負荷を与えてみたのですが、
実際にはデプロイされている多くのアプリケーションに負荷を与えないと正確な
ヒープ領域の状態は見れなく、有償のWeb負荷ツールがないと現実的に実施困難
と思っております。。

お二人のご助言をもとに、まずはverbose:gcのログを解析し、ヒープ領域の不足
でOutOfMemoryが発生したのか、Permanent領域の不足で発生したのかを切り分けて
いきたいと思います。

最後にご存知でしたら、ご教授頂ければと思っております。
●Permanent領域の最適値って推奨みたいなものはあるのでしょうか。。(?)
 ⇒JDK1.3.*ではデフォルトでMAX64MBまで拡張すると認識しています。
●HPjmeterなどで解析できるhprofで取得するプロファイルですが、一つのクラスしか解析できないのでしょうか?
 ⇒アプリのメモリリークであった場合、、数あるクラスから特定したいので。。
 ⇒プロファイルで出力されるログはかなり容量が大きいと認識しております。。
  JVMPIを使用して自作のプロファイル作成ツールを使用する以外に必要な
  プロファイルだけを取得するのは難しいのでしょうか。。?
●もしメモリリーク解析ツールのOptimizeitやJProbeをご使用の経験がございましたら
使用性のご感想をお聞きしたいです。

何卒よろしくお願いいたします。


1

スキルアップ/キャリアアップ(JOB@IT)