*目次 [#v4a08371] #contents *解消事例 [#xbdd9eda] **tomcatとjdbcとjava7 [#m6109cd6] http://ameblo.jp/vashpia77/entry-11486039940.html *メモリリークをどのように発見するか(英語) [#j232740e] http://stackoverflow.com/questions/40119/how-to-find-a-java-memory-leak *JAVAヒープサイズ・GCチューニングのまとめ [#s9181bc3] http://ise0615.blogspot.jp/2010/06/javagc.html *Java標準装備のGUIプロファイラーjvisualvm [#l9704c27] **解説ページ [#od2d2a76] http://visualvm.java.net/ja/intro.html いろいろ下にかいてありますが、 jvisualvm.exe が便利です。 **jvisualvm.exe紹介ページ [#h10a6753] http://www.atmarkit.co.jp/fjava/column/andoh/andoh43.html **リモートホストへの接続 [#dfefccd3] ***本家の説明 [#f2c7e1b4] http://visualvm.java.net/ja/gettingstarted.html ***設定方法 [#k3e86066] http://d.hatena.ne.jp/tanamon/20091016/1255674058 リモートアプリケーションからデータを取得するには、リモートの JVM で jstatd ユーティリティーが実行されている必要がありますリモートホストで実行中のアプリケーションはプロファイルできません。 ※ただし、デフォルトのポートは1099を使っており、セキュリティ的にポートが閉じられていると思います。 なので、jvisualvmをリモートで接続できない場合があると思います。 でもjvisualvmはヒープしたダンプファイルを読み込むことができ、かつ比較する機能を持っています。 sshで入れるならば、sshでリモートサーバに接続して、すでにプロセスが動いているとおもうので、 ps aux でプロセスをしらべて、比較的負荷の少ない時間帯にjmapを行います。 自分だと ps aux | grep tomcat | awk '{print $2 " " $1}' | grep tomcat | awk '{print $1}' こんな感じで、出てきたプロセスIDをxargsの-Iオプションで、パラメータとしてつかうとかしています。 それはさておき、 しばらくして、メモリリークが起きてそうなころあいを見計らって、もう一度jmapを行い、ダンプを2回とります。それは、差分をとるためです。 scpコマンドでファイルをローカルにダウンロードしてきます。 あとは、jvisualvmを使ってヒープを比較するのです。 ***jstatd を起動する方法 [#led09354] http://docs.oracle.com/javase/6/docs/technotes/tools/share/jstatd.html ***not respondingエラーが出る場合 [#xf188f3e] Unable to open socket file: target process not responding or HotSpot VM not loaded そんなときは-Fオプションを使えばいいよ。 http://www.acroquest.co.jp/webworkshop/JTSMM/backnumber.cgi?id=123545895410751 *すでに存在しているページ [#c80a2373] すでにまとめられているページがあるので、とりあえずそちらをご覧ください。 このページはそれらのページのつまみ食いという感じです。 **Javaメモリ、GCチューニングとそれにまつわるトラブル対応手順まとめ [#hc2bc33d] http://d.hatena.ne.jp/learn/20090218/p1 **JavaアプリのメモリリークやOutOfMemoryErrorの調査方法について [#ldfffb7e] http://www.syboos.jp/java/doc/how-to-do-when-OutOfMemoryError.html *jconsole [#x9a5222e] **JVMの起動オプションに次のパラメータを追加する [#l9cdb97c] たとえばポート8082で動かしてみたいとする -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=8082 **つなぎ方 [#a93c2897] たとえばポート8082で動いているとする jconsole localhost:8082 *hprof [#tdc73634] JVMTI を利用したプロファイラエージェントで、ヒープや実行時間のプロファイリングなど基本的な機能が提供されている。 *hprof を利用するには [#va5cd2b5] -agentlib:hprof これでも利用できますが、よりビジュアルに結果を見るために、eclipseでMemory Analayzer のプラグインが提供されています。 *ヘルプの出し方 [#a6970211] 下記のコマンドでヘルプを見ることができる java -agentlib:hprof=help **何の略か [#n1494841] HPROF: Heap and CPU Profiling Agent (JVMTI Demonstration Code) **使い方 [#a15e46c5] hprof usage: java -agentlib:hprof=[help]|[<option>=<value>, ...] **オプション [#w9e640fd] Option Name and Value Description Default --------------------- ----------- ------- heap=dump|sites|all heap profiling all cpu=samples|times|old CPU usage off monitor=y|n monitor contention n format=a|b text(txt) or binary output a file=<file> write data to file java.hprof[{.txt}] net=<host>:<port> send data over a socket off depth=<size> stack trace depth 4 interval=<ms> sample interval in ms 10 cutoff=<value> output cutoff point 0.0001 lineno=y|n line number in traces? y thread=y|n thread in traces? n doe=y|n dump on exit? y msa=y|n Solaris micro state accounting n force=y|n force output to <file> y verbose=y|n print messages about dumps y **Obsolete Options [#r5125362] gc_okay=y|n **例 [#u63e41f3] - Get sample cpu information every 20 millisec, with a stack depth of 3: java -agentlib:hprof=cpu=samples,interval=20,depth=3 classname - Get heap usage information based on the allocation sites: java -agentlib:hprof=heap=sites classname **メモ [#d7bab5ca] -The option format=b cannot be used with monitor=y. -The option format=b cannot be used with cpu=old|times. -Use of the -Xrunhprof interface can still be used, e.g. java -Xrunhprof:[help]|[<option>=<value>, ...] will behave exactly the same as: java -agentlib:hprof=[help]|[<option>=<value>, ...] **注意 [#f3696783] -This is demonstration code for the JVMTI interface and use of BCI, it is not an official product or formal part of the JDK. -The -Xrunhprof interface will be removed in a future release. -The option format=b is considered experimental, this format may change in a future release. **デフォルト出力 [#s0058e15] デフォルトではプロファイル結果はjava.hprof.txtというファイルに出力されます *日本語で紹介しているサイト [#t3d267f1] **Java/hprof(jvmpi) [#gb27fe23] http://apis.jpn.ph/fswiki/wiki.cgi?page=Java%2Fhprof%28jvmpi%29 **Javaでヒープダンプの取得/解析メモ その1 [#tb1a2e57] http://lenemarix2.blog28.fc2.com/blog-entry-16.html ***JavaアプリのPIDを調査 [#q49cb3a1] jps -l ***スレッドダンプ [#n2e6fe61] jstack PID ***ガーベッジ・コレクションのスナップショット [#g9690ef3] jstat -gc 5756 250 10 ***jmap [#t6430fd8] プロセス番号を調べてからつかいます。 自分はcygwinとかいれているので、 tasklist | nkf | grep java とかで調べています。 バイナリファイルで結果を出力する例 jmap -dump:format=b,file=出力ファイルパス プロセス番号 出てきたファイルを見るには jhat -J-Xmx700m jmapでの出力ファイルパス *Eclipse Memory Analyzer [#v6473080] 以下紹介サイトより抜粋 -Leak Suspects - リークしてそうなのはこいつらだ -Dominator tree - 大きいオブジェクトを一覧で見よう -Path to GC Roots - こいつは誰が参照してる? リークを特定する為の基本的な流れとしては、Leak Suspects で怪しいところを教えてもらい、Dominator Tree*1 で怪しいオブジェクトを一覧 & 構造を調べ、Path to GC Roots でリーク元を特定する、という様な流れになります。 詳しくは下記の紹介サイトをごらんください。 **公式サイト [#p1ef8d1f] http://eclipse.org/mat/downloads.php **インストール紹介サイト [#v912d614] http://xiangcai.at.webry.info/201009/article_7.html ※現時点では、MATの更新サイトのアドレスがバージョンアップで変更になっていました。 http://download.eclipse.org/mat/1.2/update-site/ **紹介サイト [#cce1c24e] http://tlync.hateblo.jp/entry/20111220/1324372308 **使い方メモ [#r4be3fef] 1.Eclipseのプラグインなので適当にインストール。 2.Eclipseの実行の構成を開いて、引数タブのVM引数に以下のどちらかを設定する。 hprofファイルだけを出力します。 -Xrunhprof:heap=dump,format=b,file=./${project_name}.hprof hprofファイルも出力されるけど関係ないファイルが全部出力される。 -agentlib:hprof=heap=dump,format=b 3.普通に実行 4.hprofファイルが出力されるので開くと、メモリの使用状態が表示される。 ***Eclipseでtomcatの場合 [#k629cb96] http://wiki.eclipse.org/index.php/MemoryAnalyzer#Getting_a_Heap_Dump http://tomcat.10.x6.nabble.com/How-to-generate-heap-dump-in-Tomcat-5-5-Windows-td4643861.html ***情報源 [#p1f16f5c] http://odasusu.hatenablog.com/entry/20080730/1217419266 *PrintClassHistogramオプション [#q1f068d7] そのプロセスに対して一定間隔ごとにSIGQUITシグナルを送信する。 **利用方法 [#dd5fe57d] Java起動時に以下のオプションを追加する java -verbose:gc -XX:+PrintClassHistogram TestMain ***UNIX系で情報を取得 [#b266e683] crontabで実行するコマンド kill -3 <java pid> ***情報源 [#d999e061] http://www.atmarkit.co.jp/fjava/rensai4/troublehacks08/troublehacks08_2.html