javaトラブルに備えよう #jjug_ccc #ccc_h2
Post on 25-Jan-2015
28.960 Views
Preview:
DESCRIPTION
TRANSCRIPT
【JJUG CCC 2014 Spring H-‐2】
Javaトラブルに備えよう 日本Javaユーザグループ 上妻 宜人 (あげつま のりと)
はてなブログ : n-agetsuma.hatenablog.com
自己紹介
上妻 宜人 (あげつま のりと)
n 電話の裏側を作っている会社で働いています
n Java/APサーバの社内技術サポート、トラブル解析
n Blog 『見習いプログラミング日記』
【JJUG CCC 2014 Spring H-‐2】
Java Heap Size
6me
-‐Xmx: 4G
3GB
2GB
1GB
java.lang.OutOfMemoryError: Java heap space
【JJUG CCC 2014 Spring H-‐2】
Javaトラブルランキング (私の感覚調べ)
第1位
OutOfMemoryError の発生 (Heap、Perm、”unable to create new na6ve Thread”)
第2位
スローダウン / タイムアウト (SQL遅延、無限ループ、JTAタイムアウト など)
第3位
OSの設定漏れ (“Too many open files” など)
【JJUG CCC 2014 Spring H-‐2】
GCログがない クラスヒストグラムがない
ヒープダンプがない スレッドダンプがない
プロファイラがアタッチできない APログが出てない
JMXモニタリング情報がない 【JJUG CCC 2014 Spring H-‐2】
本日のコンテンツ
OutOfMemoryErrorに備える • GCログによる過度なヒープ消費の発見
• クラスヒストグラム / ヒープダンプによる解析
スローダウン / タイムアウトに備える • スレッドダンプ と hprofプロファイラ
• JTAタイムアウトの罠
OSの設定漏れに備える • too many open files
• unable to create new na6ve thread
【JJUG CCC 2014 Spring H-‐2】
トラブル 第1位
トラブル 第2位
トラブル 第3位
本日のコンテンツ
OutOfMemoryErrorに備える • GCログによる過度なヒープ消費の発見
• クラスヒストグラム / ヒープダンプによる解析
スローダウン / タイムアウトに備える • スレッドダンプ と hprofプロファイラ
• JTAタイムアウトの罠
OSの設定漏れに備える • too many open files
• unable to create new na6ve thread
【JJUG CCC 2014 Spring H-‐2】
トラブル 第1位
トラブル 第2位
トラブル 第3位
【JJUG CCC 2014 Spring H-‐2】
Meta Space
Other JVM Mem
Eden Survivor
Old(Tenured) Young(New)
OutOfMemoryとは : Javaヒープ振り返り
S0 S1
User agetsuma = new User(“Norito Agetsuma”);
java.lang.OutOfMemoryError: Java heap space
ヒープが足りない
【JJUG CCC 2014 Spring H-‐2】
OutOfMemoryErrorに備える
【1.予兆の確認】
Java Heap
6me
-‐Xmx: 4G
3GB
2GB
1GB
『GCログの出力』
【2.発生時の解析】
『ヒープダンプ』
『クラスヒストグラム』 num #instances #bytes class name -‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐ 1 10000 250000 java.lang.String 2 8000 200000 foo.Sample
Old New S0 S1
.hprofファイル(バイナリ形式)
負荷大
負荷中
25.471: [GC (Alloca6on Failure) 192453K-‐>98057K(506816K), 0.1321301 secs]
負荷小
GCログの取得
【JJUG CCC 2014 Spring H-‐2】
java -Xms4g –Xmx4g –XX:MaxMetaspaceSize=512m-Xloggc:${WILDFLY}/standalone/log/ gc.log.`date +%Y%m%d%H%M%S`-XX:+PrintGCDetails -XX:+PrintGCDateStamps-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M
改行しない
Java起動オプションにあらかじめ設定する必要がある
GCログ出力の基本設定部分
【JJUG CCC 2014 Spring H-‐2】
java -Xms4g –Xmx4g –XX:MaxMetaspaceSize=512m-Xloggc:${WILDFLY}/standalone/log/ gc.log.`date +%Y%m%d%H%M%S`-XX:+PrintGCDetails -XX:+PrintGCDateStamps-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M
改行しない
• -Xloggc 出力先パスの指定
• -XX:+PrintGCDetails 詳細レベルでGCロギングする
• -XX:+PrintGCDateStamps GCログ各行に時刻を出力 (デフォルトはJVM起動からの経過時間のみ)
java -Xms4g –Xmx4g –XX:MaxMetaspaceSize=512m-Xloggc:${WILDFLY}/standalone/log/ gc.log.`date +%Y%m%d%H%M%S`-XX:+PrintGCDetails -XX:+PrintGCDateStamps-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M
再起動時のGCログ上書きを防止する
【JJUG CCC 2014 Spring H-‐2】
改行しない
ファイル名: gc.log.20140510123200
参考: nekopの日記 GCログを上書きしないためのTips hjp://d.hatena.ne.jp/nekop/20111017/1318812320
年 月 日 時 分 秒
GCログのローテーション(JDK6u34〜/7u2〜/8)
【JJUG CCC 2014 Spring H-‐2】
JavaVM gc.log.0 (最大10MB)
サイズローテーション
java -Xms4g –Xmx4g –XX:MaxMetaspaceSize=512m-Xloggc:${WILDFLY}/standalone/log/ gc.log.`date +%Y%m%d%H%M%S`-XX:+PrintGCDetails -XX:+PrintGCDateStamps-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M
改行しない
JDK8でGCログも少し進化しています
【JJUG CCC 2014 Spring H-‐2】
Java HotSpot(TM) 64-‐Bit Server VM (25.5-‐b02) for linux-‐amd64 JRE (1.8.0_05-‐b13), built on Mar 18 2014 00:29:27 by "java_re" with gcc 4.3.0 20080428 (Red Hat 4.3.0-‐8) Memory: 4k page, physical 1536436k(664260k free), swap 3080184k(2757976k free) CommandLine flags: -‐XX:Ini6alHeapSize=536870912 -‐XX:MaxHeapSize=536870912 -‐XX:+PrintGC -‐XX:+PrintGCDateStamps -‐XX:+PrintGCDetails -‐XX:+PrintGCTimeStamps -‐XX:+UseCompressedClassPointers -‐XX:+UseCompressedOops
• バージョン/メモリ情報/コマンドライン引数のファイル先頭出力
• -‐XX:+PrintGCCause(JDK7u40〜) のデフォルト化
25.471: [GC (Alloca6on Failure) 192453K-‐>98057K(506816K) ...
GCViewerでログをグラフ化する
【JJUG CCC 2014 Spring H-‐2】
hjps://github.com/chewiebug/GCViewer
GC後メモリ使用量が 一定に保たれていれば正常
【JJUG CCC 2014 Spring H-‐2】
OutOfMemoryErrorに備える
【1.予兆の確認】
Java Heap
6me
-‐Xmx: 4G
3GB
2GB
1GB
『GCログの出力』
【2.発生時の解析】
『ヒープダンプ』
『クラスヒストグラム』 num #instances #bytes class name -‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐ 1 10000 250000 java.lang.String 2 8000 200000 foo.Sample
Old New S0 S1
.hprofファイル(バイナリ形式)
負荷大
負荷中
25.471: [GC (Alloca6on Failure) 192453K-‐>98057K(506816K), 0.1321301 secs]
負荷小
ヒープダンプの取得
【JJUG CCC 2014 Spring H-‐2】
コマンドラインで取得
• JDK6 ${JAVA_HOME}/bin/jmap -‐dump:live,format=b,file=<filename>
• JDK7u4以降 (jmapも継続して有効) ${JAVA_HOME/bin/jcmd <pid> GC.heap_dump <filename>
OOMエラー時に自動取得 (Java起動オプション)
• -‐XX:+HeapDumpOnOutOfMemoryError
• -‐XX:HeapDumpPath=${WILDFLY}/standalone/log/
負荷が大きいため、商用ではOOMエラー時自動取得がお勧め
ヒープダンプ解析 : Eclipse Memory Analyzer
【JJUG CCC 2014 Spring H-‐2】
hjp://www.eclipse.org/mat/ からダウンロード
【Leak Suspects】 ヒープ中に多いオブジェクトの表示
【JJUG CCC 2014 Spring H-‐2】
OutOfMemoryErrorに備える
【1.予兆の確認】
Java Heap
6me
-‐Xmx: 4G
3GB
2GB
1GB
『GCログの出力』
【2.発生時の解析】
『ヒープダンプ』
『クラスヒストグラム』 num #instances #bytes class name -‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐ 1 10000 250000 java.lang.String 2 8000 200000 foo.Sample
Old New S0 S1
.hprofファイル(バイナリ形式)
負荷大
負荷中
25.471: [GC (Alloca6on Failure) 192453K-‐>98057K(506816K), 0.1321301 secs]
負荷小
クラスヒストグラム
【JJUG CCC 2014 Spring H-‐2】
8761: num #instances #bytes class name -‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐ 1: 3902054 104446080 [B 2: 1003304 64211456 org.hibernate.engine.spi.En6tyEntry 3: 1069377 60752992 [Ljava.lang.Object; 4: 1061657 53156392 [C 5: 1300009 41601968 [[B 6: 1092928 34973696 java.u6l.HashMap$Node 7: 2008549 32136784 java.lang.Integer 8: 1003304 32105728 org.hibernate.engine.internal.En6tyEntryContext 9: 1061269 25470456 java.lang.String 10: 1003304 24079296 net.agetsuma.performancetest.en6ty.Member
Javaヒープを多く占めているクラスをテキスト形式で取得
クラスヒストグラム
【JJUG CCC 2014 Spring H-‐2】
8761: num #instances #bytes class name -‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐ 1: 3902054 104446080 [B 2: 1003304 64211456 org.hibernate.engine.spi.En6tyEntry 3: 1069377 60752992 [Ljava.lang.Object; 4: 1061657 53156392 [C 5: 1300009 41601968 [[B 6: 1092928 34973696 java.u6l.HashMap$Node 7: 2008549 32136784 java.lang.Integer 8: 1003304 32105728 org.hibernate.engine.internal.En6tyEntryContext 9: 1061269 25470456 java.lang.String 10: 1003304 24079296 net.agetsuma.performancetest.en6ty.Member
Javaヒープを多く占めているクラスをテキスト形式で取得
JPAエンティティの大量ロード。 JPQL直すか、ScrollableResults使うなどの対処。
クラスヒストグラムの取得
【JJUG CCC 2014 Spring H-‐2】
コマンドラインで取得
• JDK6 ${JAVA_HOME}/bin/jmap -‐histo:live <pid>
• JDK7u4以降 (jmapも継続して有効) ${JAVA_HOME/bin/jcmd <pid> GC.class_histogram
CTRL + BREAK (Windows) / kill -‐3 で標準出力
• -‐XX:+PrintClassHistogram
• Windowsサービス登録されたTomcatの解析時に便利
よくあるOOMエラーのパターン1 【突出型】
• ある機能を動かすとOutOfMemoryErrorが発生する
• 多くはDBやファイルからの大量ロードが原因
【JJUG CCC 2014 Spring H-‐2】
青のUsedHeapが急上昇。
このパターンの解析に欲しい情報
• エラー時にどんなコードが動いていたか (アプリログ)
• OutOfMemoryErrorが発生したタイミングのヒープダンプ
【JJUG CCC 2014 Spring H-‐2】
突出型OOMエラー解決への情報収集
• Java起動オプションに普段から設定しておく
• OOMエラー発生時に自動的にヒープダンプで状況保存
• 古くからあるJava起動オプション (1.4.2u12, 5u7 〜)
【JJUG CCC 2014 Spring H-‐2】
-‐XX:+HeapDumpOnOutOfMemoryError
-‐XX:HeapDumpPath=${WILDFLY}/standalone/log/
よくあるOOMエラーのパターン2 【じわじわ型】
• 長い時間をかけてOutOfMemoryErrorに至るパターン
• 再現に時間がかかる or 再現しないので厄介
• 原因例: ORマッパキャッシュ/自作キャッシュ/セッション肥大化
【JJUG CCC 2014 Spring H-‐2】
このパターンの解析に欲しい情報
• 時系列のヒープ情報 (何がじわじわ増えているのか)
• 商用のみ再現するケースも多く、OutOfMemoryErrorに至る前に
負荷の大きいヒープダンプを取得するのは困難
【JJUG CCC 2014 Spring H-‐2】
なるべく軽い負荷で 時系列ヒープ情報を比較したい
【JJUG CCC 2014 Spring H-‐2】
じわじわ型OOMエラー解決への情報収集
『定期的なクラスヒストグラムの収集』
JDK6以前 jmap -‐histo:live <pid>
JDK7,8 jcmd <pid> GC.class_histogram
• ヒープダンプと比較して、負荷も軽いため商用で使いやすい
• cronを利用して定期的に取得、テキストデータをグラフ化
• 増加傾向クラスの利用部分のソースコードをチェック
OSSツール HeapStats で情報収集する
• クラスヒストグラムを定期取得&グラフ化するのは面倒
• HeapStatsではJVMにアタッチ、低オーバヘッドで自動収集
• 専用アナライザでグラフ表示も可能
hjp://icedtea.classpath.org/wiki/HeapStats/jp
クラス別ヒープ使用量の積み上げグラフ 参照ツリー表示
java -Xms?g -Xmx?g -XX:MaxMetaspaceSize=?m
-Xloggc:${WILDFLY}/standalone/log/
gc.log.`date +%Y%m%d%H%M%S`-XX:+PrintGCDetails -XX:+PrintGCDateStamps-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=${WILDFLY}/standalone/log/
まとめ: OOMエラーに備えたJVMオプション
GC ログ
ヒープ ダンプ
【JJUG CCC 2014 Spring H-‐2】
本日のコンテンツ
OutOfMemoryErrorに備える • GCログによる過度なヒープ消費の発見
• クラスヒストグラム / ヒープダンプによる解析
スローダウン / タイムアウトに備える • スレッドダンプ と hprofプロファイラ
• JTAタイムアウトの罠
OSの設定漏れに備える • too many open files
• unable to create new na6ve thread
【JJUG CCC 2014 Spring H-‐2】
トラブル 第1位
トラブル 第2位
トラブル 第3位
スレッドダンプとは
Thread A
Thread B
Thread C
Thread D
wait wait
wait
ThreadDump 1回目
ThreadDump 2回目
ThreadDump 3回目
• コマンド実行時のJavaスレッド状態を出力する
• その瞬間、JavaVMで何が動いていたのか調査するために使う
【JJUG CCC 2014 Spring H-‐2】
スレッドダンプの取得
【JJUG CCC 2014 Spring H-‐2】
• 少なくとも1.4.2にはある
kill -‐3 <pid>
• JDK5以降 ${JAVA_HOME}/bin/jstack <pid>
• JDK7u4以降 (kill -‐3 / jstackも継続して有効) ${JAVA_HOME/bin/jcmd <pid> Thread.print
• Windowsサービス登録されたTomcat
画面右下の Tomcatアイコンをクリック
スレッドダンプ出力例
"default task-‐10" prio=5 6d=0x00007fef5bb8d000 nid=0xb307 wai6ng on condi6on [0x000000011090a000] java.lang.Thread.State: TIMED_WAITING (parking) at sun.misc.Unsafe.park(Na6ve Method) -‐ parking to wait for <0x00000007fea15470> at java.u6l.concurrent.locks.LockSupport.parkNanos … 〜 省略 〜 at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnec6on… at slowweb.SlowServlet.processRequest(SlowServlet.java:44) at slowweb.SlowServlet.doGet(SlowServlet.java:78) at javax.servlet.hjp.HjpServlet.service(HjpServlet.java:687)
アプリケーション のスタック
WildFly内部 のスタック
【JJUG CCC 2014 Spring H-‐2】
スレッドダンプ出力例
"default task-‐10" prio=5 6d=0x00007fef5bb8d000 nid=0xb307 wai6ng on condi6on [0x000000011090a000]
java.lang.Thread.State: TIMED_WAITING (parking) at sun.misc.Unsafe.park(Na6ve Method) -‐ parking to wait for <0x00000007fea15470> at java.u6l.concurrent.locks.LockSupport.parkNanos … 〜 省略 〜 at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnec6on… at slowweb.SlowServlet.processRequest(SlowServlet.java:44) at slowweb.SlowServlet.doGet(SlowServlet.java:78) at javax.servlet.hjp.HjpServlet.service(HjpServlet.java:687)
アプリケーション のスタック
WildFly内部 のスタック
データソースプール枯渇時の接続取得待ちスレッドの例
【JJUG CCC 2014 Spring H-‐2】
可視化ツールその1 『侍』
【JJUG CCC 2014 Spring H-‐2】
hjp://samuraism.jp/samurai/ja/index.html からダウンロード
スレッドの状態を時系列に表示するのに便利
スレッドの増加傾向や、ブロックされ具合が一目でわかる
可視化ツールその2 『ThreadLogic』
【JJUG CCC 2014 Spring H-‐2】
hjps://java.net/projects/threadlogic からダウンロード
怪しいスレッド(確認すべきスレッド)をマーキングしてくれる
特にWebLogicServer/JRockit向けが精度が高い
よくある突然の無応答トラブル例
• 無限ループ • java.u6l.HashMapへのマルチスレッドアクセス
• java.u6l.concurrent.ConcurrentHashMapに変更する
• SQLの応答待ち • コネクションプール枯渇を併発して、全機能停止もある
• SQL実行計画を確認し、インデックス付与やSQL書き直し
• java.sql.setQueryTimeout(int seconds) で予防措置
【JJUG CCC 2014 Spring H-‐2】
[PostgreSQLの注意] 9.2からsetQueryTimeoutに対応。 〜9.1では『set statement_6meout to <second>』をJDBC実行
【JJUG CCC 2014 Spring H-‐2】
JDK付属hprofプロファイラ
java –agentlib:hprof=CPU=samples,file=<出力先指定>
TRACE 301470: sun.nio.ch.EPollArrayWrapper.epollWait(EPollArrayWrapper.java) sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) CPU SAMPLES BEGIN (total = 145881) Sun May 11 12:09:05 2014 rank self accum count trace method 1 86.56% 86.56% 126270 301470 sun.nio.ch.EPollArrayWrapper.epollWait 2 7.21% 93.77% 10521 302418 java.net.SocketInputStream.socketRead0 3 1.06% 94.83% 1552 300362 java.lang.ClassLoader.defineClass0
• SIGQUIT(kill -‐3)または、JavaVM終了時にテキスト出力
【JJUG CCC 2014 Spring H-‐2】
hprof=CPU=samples の特徴
• 集計対象は『サンプリング時にアクティブなスレッド』のみ
• sleep()やwait()による性能遅延は集計対象外
private void sleepAndWait() … { Thread.sleep(5000); wait(5000);}
private List<String> moreLoop() { return Stream.generate(() -> "slow") .limit(100000) .collect(toList());}
【検出できるもの】
• 長いアクティブスレッド
• ループ系性能遅延 等
【検出できないもの】
• sleepスレッド
• waitスレッド 等
【JJUG CCC 2014 Spring H-‐2】
商用での定常的収集にはJFR(有償) Java Flight Recorder (JDK7u40以降)
hjp://docs.oracle.com/javase/7/docs/technotes/guides/jfr/usingjfr.html
【JJUG CCC 2014 Spring H-‐2】
引っかかることの多いタイムアウト
hjp://www.fancyicons.com/free-‐icon/112/hardware-‐icon-‐set/free-‐server-‐icon-‐png/
Webサーバ
mod
_jk
DBサーバ
mod_jk : reply_6meout (worker.proper6es) • APサーバからの最大応答待ち時間 (デフォルト無限)
• タイムアウト時、ブラウザには502が返る
APサーバ
select …
update…
JTAトランザクションタイムアウト
• デフォルト値 : WildFly8 5分 / WebLogic12c 30秒
• タイムアウトを経過しても、止まらないことがある
【JJUG CCC 2014 Spring H-‐2】
JTAタイムアウト後も止まらないケース
hjp://www.fancyicons.com/free-‐icon/112/hardware-‐icon-‐set/free-‐server-‐icon-‐png/
• 応答のないSQLクエリ受信待ちの場合
• 同期ソケットI/O中にはinterrrupt()に反応しないのが要因
• コネクションプールも浪費する要因なので厄介
"default task-‐2” … java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Na6ve Method) at java.net.SocketInputStream.read(SocketInputStream.java:150) … at org.postgresql.core.v3.QueryExecutorImpl.execute
【こんなスレッドダンプには注意】
【JJUG CCC 2014 Spring H-‐2】
WildFly8の場合はWARNログがでてきます
WARN ARJUNA012120: Thread[…] not responding to interrupt when cancelling TX … -‐-‐ worker marked as zombie and TX scheduled for mark-‐as-‐rollback
1. 割込みに反応しないので、ゾンビとしてマーキング
WARN ARJUNA012113: Transac6onReaper::doCancella6ons worker Thread[Transac6on Reaper Worker 0,5,main] missed interrupt when cancelling TX 0:ffff7f000001:-‐87f41d4:536f3485:49
-‐-‐ exi6ng as zombie (zombie count decremented to 0)
2. SQLが返ってきたので、ゾンビスレッドを終了
(ゾンビとしてマーク) (ロールバック確定)
(ゾンビスレッドが終了して、残りのゾンビは0になった)
【JJUG CCC 2014 Spring H-‐2】
SQLクエリタイムアウトを併用して対処
• JDBC SQLタイムアウト • java.sql.statement.setQueryTimeout(int seconds)• スレッド割込みではなく、キャンセル要求送信で実現
• APサーバ機能 • WildFly8 『set-‐tx-‐query-‐6meout』の設定 (デフォルト無効)
• WebLogic12c 『文タイムアウト』の設定 (デフォルト無限)
[再びPostgreSQLの注意] 9.2からsetQueryTimeoutに対応。 〜9.1では『set statement_6meout to <second>』をJDBC実行
本日のコンテンツ
OutOfMemoryErrorに備える • GCログによる過度なヒープ消費の発見
• クラスヒストグラム / ヒープダンプによる解析
スローダウン / タイムアウトに備える • スレッドダンプ と hprofプロファイラ
• JTAタイムアウトの罠
OSの設定漏れに備える • too many open files
• unable to create new na6ve thread
【JJUG CCC 2014 Spring H-‐2】
トラブル 第1位
トラブル 第2位
トラブル 第3位
Caused by: java.io.FileNotFoundExcep6on: /dev/null
(Too many open files)
【JJUG CCC 2014 Spring H-‐2】
ファイルディスクリプタが足りない?
init.d配下の起動スクリプトに ulimit –n 65536
/etc/security/limits.conf
【JJUG CCC 2014 Spring H-‐2】
lsof (list open files) : オープン中ファイル一覧
# lsof -‐p <java_pid> COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME java 14090 agetsuma 337w REG 253,2 96 524235 /home/test/sandbox/file/0 java 14090 agetsuma 338w REG 253,2 96 524237 /home/test/sandbox/file/1 java 14090 agetsuma 339w REG 253,2 96 524239 /home/test/sandbox/file/2 java 14090 agetsuma 340w REG 253,2 96 524241 /home/test/sandbox/file/3 …
『足りない』のではなく、シンプルにclose()漏れの可能性もある。
事実を把握した上で対処することが大切
【JJUG CCC 2014 Spring H-‐2】
スレッド数上限に達したときも情報収集
【JJUG CCC 2014 Spring H-‐2】
java.lang.OutOfMemoryError : unable to create new thread
• いきなり /etc/security/limits.conf の nproc を拡大しない
• スレッドダンプ(jcmd <pid> Thread.print) を取得して事実確認
• 『足りない』が原因とは限らない
• 余談ですが、このOOMエラーではヒープダンプでません
GCログとエラー時自動ヒープダンプを有効に
java -Xms?g -Xmx?g -XX:MaxMetaspaceSize=?m
-Xloggc:${WILDFLY}/standalone/log/
gc.log.`date +%Y%m%d%H%M%S`-XX:+PrintGCDetails -XX:+PrintGCDateStamps-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=${WILDFLY}/standalone/log/
GC ログ
ヒープ ダンプ
【JJUG CCC 2014 Spring H-‐2】
テスト環境でのOutOfMemoryエラーでは
積極的にヒープダンプを取得
• JDK6 ${JAVA_HOME}/bin/jmap -‐dump:live,format=b,file=<filename>
• JDK7u4以降 (jmapも継続して有効)
${JAVA_HOME/bin/jcmd <pid> GC.heap_dump <filename>
【JJUG CCC 2014 Spring H-‐2】
商用などヒープダンプが厳しい場合は
クラスヒストグラムを収集
• JDK6 ${JAVA_HOME}/bin/jmap -‐histo:live <pid>
• JDK7u4以降 (jmapも継続して有効)
${JAVA_HOME/bin/jcmd <pid> GC.class_histogram
【JJUG CCC 2014 Spring H-‐2】
ヒープ情報収集には HeapStats もおすすめ
【JJUG CCC 2014 Spring H-‐2】
クラス別ヒープ使用量の積み上げグラフ 参照ツリー表示
hjp://icedtea.classpath.org/wiki/HeapStats/jp
アプリケーションが止まったら、
再起動する前にスレッドダンプを収集
【JJUG CCC 2014 Spring H-‐2】
• 少なくとも1.4.2にはある
kill -‐3 <pid>
• JDK5以降 ${JAVA_HOME}/bin/jstack <pid>
• JDK7u4以降 (kill -‐3 / jstackも継続して有効) ${JAVA_HOME/bin/jcmd <pid> Thread.print
あれ?なんだか遅いな と思ったら
hprofでプロファイリング
【JJUG CCC 2014 Spring H-‐2】
java -‐agentlib:hprof=cpu=samples,file=<output.txt>
CPU SAMPLES BEGIN (total = 145881) Sun May 11 12:09:05 2014 rank self accum count trace method 1 86.56% 86.56% 126270 301470 sun.nio.ch.EPollArrayWrapper.epollWait 2 7.21% 93.77% 10521 302418 java.net.SocketInputStream.socketRead0 3 1.06% 94.83% 1552 300362 java.lang.ClassLoader.defineClass0
【JJUG CCC 2014 Spring H-‐2】
# lsof -‐p <java_pid> COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME java 14090 agetsuma 337w REG 253,2 96 524235 /home/test/sandbox/file/0 java 14090 agetsuma 338w REG 253,2 96 524237 /home/test/sandbox/file/1 java 14090 agetsuma 339w REG 253,2 96 524239 /home/test/sandbox/file/2 java 14090 agetsuma 340w REG 253,2 96 524241 /home/test/sandbox/file/3 …
『too many open files』が出たら、
すぐに拡張せずに lsof で事実の確認
top related