HotSpot server VMのバグ
JDK1.4.2からJDK1.6.0にあげたら、こんなエラー出た。
# # A fatal error has been detected by the Java Runtime Environment: # # java.lang.OutOfMemoryError: requested 2147483664 bytes for Chunk::new. Out of swap space? # # Internal Error (allocation.cpp:215), pid=26889, tid=1083394400 # Error: Chunk::new # # JRE version: 6.0_21-b06 # Java VM: Java HotSpot(TM) 64-Bit Server VM (17.0-b16 mixed mode linux-amd64 ) # An error report file with more information is saved as: # /usr/local/jakarta-tomcat-5.0.30/bin/hs_err_pid26889.log # # If you would like to submit a bug report, please visit: # http://java.sun.com/webapps/bugreport/crash.jsp #
GCのログを追う限りではメモリが足らないわけではなく、突発的に大量のメモリが必要な処理をしたわけでもなく、突如2Gbyteのchunkをアロケートしようとして落ちるという現象。(物理メモリの空きがほとんど無くて、swapは1Gしかないので・・・)
とりあえず再起動しても、数時間後に同じように落ちる。しかも要求してるchunkのサイズは決まって2147483664 bytes(2^31 -16)。なんかおかしい。
VM起動時の引数は以下のとおり。(一部抜粋)
-Xms700m -Xmx700m -Xnoclassgc -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:MaxGCPauseMillis=30 -XX:GCPauseIntervalMillis=140
G1GCなんてファンキーなものを使っていたので、これをやめて以下のようにしてみましたが(さまざまな事情により数字が色々変わってます)
-Xss512k -Xms720m -Xmx720m -Xmn320m -XX:SurvivorRatio=32 -XX:TargetSurvivorRatio=20 -XX:MaxTenuringThreshold=32 -XX:PermSize=80m -XX:MaxPermSize=80m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseParNewGC -XX:ParallelGCThreads=2
それでも同じように落ちる。G1GCは関係なかったです。
で、調べてみるとどうやらHotSpot server VMのバグで、JITコンパイラが原因らしいとのこと。*1
というわけで、32bitのJDKを入れて -client でclient VMを使うようにしたら、問題は発生しなくなりました。なりましたが、client VMでずっと動かすのはちょっと。。。
スレッドダンプからJITコンパイラがコンパイルしようとしていたクラスとメソッドの情報が出るので、
Current CompileTask: C2:2054 ! my.package.name.ClassName.methodName(parameter...)Lmy.package.name.ReturnType; (809 bytes)
この情報に基づいて、JITコンパイルから該当メソッドを除外するオプションを指定。
-XX:CompileCommand=exclude,my/package/name/ClassName,methodName
で、64bit server VMに戻したところ、無事稼働中。バグを踏んだメソッドの何がいけなかったのかは。。。不明です。
あと、Sun、というかOracleのバグ情報を探そうとしたんですが、bugs.sun.comがものすごく不親切かつ検索がタイムアウトするので断念。たぶんJDK1.6.0 update 18あたりから既に発生していたようです。要注意。