Quitada ブログ HAX

Hatena Blog でも Quitada ブログ

Java 仮想マシン(JVM)の仕様を超えてますよ…

[rakuten:book:10975686:detail]
Java 仮想マシン仕様 4.10 節に制限事項があります。これらのひとつが、1 メソッドの最大サイズは 65,536 バイト(64KB)という制限。こちら。

The amount of code per non-native, non-abstract method is limited to 65536 bytes by the sizes of the indices in the exception_table of the Code attribute (§4.7.3), in the LineNumberTable attribute (§4.7.8), and in the LocalVariableTable attribute (§4.7.9).

Java 言語で普通にコーディングする方々から見ると「1 メソッドが 64KB 超っていう場合はまずないでしょ」と思うことが多いけど、最近はこの制限にひっかかるパターンがでてきたりしているんですよね。それは、JSP をコーディングして、さらにタグライブラリを多用した場合です。というのは、何も考えずに JSP 書いてると、それを javaコンパイルした場合、全て service() メソッドに展開され、さらにタグライブラリを多用すると、多くの JSP コンパイラ実装で、そのまま java コードとしてやはり service() メソッドにインライン展開され、64KB の制限に簡単にぶちあたりやすいのです。

この制限による弊害の一例としては、BEA 社の dev2dev に掲載されている以下の日本語ソリューションがあげられます。

S-40080:
タイトル アプリケーション初回実行時やデプロイ時に、不意に NoClassDefFoundError や JVM クラッシュが発生する

なんらかの方法で 64KB の制限を越えてコンパイルできてしまったアプリケーションを実行したりデプロイしようと、意味不明な NoClassDefFoundError がでたり JVM クラッシュが発生したりするというものです。

普通、64KB を超えたメソッドを含む java コードを javac でコンパイルしようとすると、コンパイルエラーになってしまいます。一方、最近の WebLogic Server はアプリケーションのコンパイルは javac ではなく、Javelin というコンパイラフレームワークを使っていて、どうやら 64KB の制限のチェックしてないらしくコンパイルが通ってしまうんですね。その結果、いざアプリケーションを実行したりデプロイしたりすると、想定外のエラーになってしまうようですね。ま、-Xverify:all をつけておけば「64KB の制限を超えてまーす」という比較的わかりやすいエラーがでてくるようです。

そもそも、64KB の制限にひっかかるようなアホなアプリケーションを記述するのが悪い!といえばそれまでですけどねー。でも、JSP から自動生成されるコードのことなんて、普通考えないので、そこらへんは JSPコンパイルフレームワークで、自動的にメソッド分割するとかして吸収してほしいところです。

#と、なんでもかんでもやってしまうと、そういう制限のことなんか知らない開発者をどんどん増やしてしまい、それはそれでどうかと思う。