この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
Tomcat起動時にスタックオーバーフローが発生した際の対象方法をご紹介します。
■ Tomcat起動が起動しない・・・
ある日、これまで正常に起動していたTomcatが起動しなくなりました。
ログを見ると以下の出力。
Cannot load JDBC driver class 'oracle.jdbc.OracleDriver'
java.lang.StackOverflowError
at java.util.Stack.empty(Stack.java:96)
at sun.misc.URLClassPath.getLoader(URLClassPath.java:283)
at sun.misc.URLClassPath.getResource(URLClassPath.java:168)
at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at sun.misc.Launcher$ExtClassLoader.findClass(Launcher.java:229)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:295)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1595)
...
StackOverflowErrorが発生しているようです。
■ スタックとは?
JVMのメモリ構造はスタックとヒープに大別されます。
ヒープはオブジェクトのインスタンスなどが保存される広大な領域で、GCの対象です。
一方スタックはメソッド起動時にローカル変数などを保存する領域です。
あまりスタックが足りなくなる場合は無いのですが、意図しないケースだと再帰メソッドの終了条件の書き忘れなどで発生します。
ただ、今回の場合はアプリ起動時にローカル変数をキャッシュするようにしたことによるスタックサイズの増加でした。
そのため、対処としては最大スタックサイズを増やすしかなさそうです。
■ 最大スタックサイズの設定
最大スタックサイズの設定はJVMの起動パラメータの
-Xss512k
の値で変更します。
では、どれくらい増やせばよいのか・・・?
大きければいいという訳ではありません。最大スタックサイズを非常に大きな値に設定すると、
パフォーマンスが低下する可能性があります。
まずは現在の設定値 or デフォルト値の2倍程度にして様子をみるのがいいでしょう。
■ まとめ
通常スタックサイズが足りなくなることは少ないかと思いますが、もし足りなくなったら上記設定で対処することができます。
もちろんその前に、無限ループなどが発生していないか確認するのをお忘れなく!