かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Tomcat3.3とTomcat5でのJSPから生成されるJavaコードの違い

元になるJSP

<html>
<body>
  <%= "Hello world " %>
</body>
</html>

出力されるJavaのコード
Tomcat3.3だと、以下のような雰囲気で出力されます

out.write("<html>\n<body>\n  ");
out.write("Hello world");
out.write("\n</body></html>\n");

Tomcat5.xだと以下のような雰囲気で出力されます

out.write("<html>\n");
out.write("<body>\n");
out.write("  ");
out.write("Hello world");
out.write("\n");
out.write("</body>\n");
out.write("</html>\n");

人間が見る分にはTomcat5系のほうが見やすいですが、冗長な表現になっています。行単位での出力が基本ポリシーになったのかな?

ちょっと問題が・・・

まぁどうでもいいかなと思ってたんですが、この差ではまりました。
長いJSPで、Tomcat3.3では動いてたけど、Tomcat5.xにうつすと1メソッド64KBの制限にひっかかって

try 文のコードが大きすぎます。
コードが大きすぎます。

というエラーが出るようになってしまった・・・。
まぁそんなJSPが、どうよ?っていう話はあるのですが、とりあえずTomcat5.xの生成するJavaコードをコンパクトにできないか調べてみたので、もしかしたら誰かの役に立つかもしれないので書いておきます。

JspServletのパラメータ設定

%CATALINA_HOME%\conf\web.xmlにあるJspServletの定義に以下のパラメータを追加します。

パラメータ名 説明
trimSpaces true スクリプトレットとかのある行をtrimしてくれる
genStrAsCharArray true 文字列をcharの配列にしてくれる

*1
パラメータを設定した後のservletタグは以下のようになりました。

  <servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
      <param-name>fork</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>xpoweredBy</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>mappedfile</param-name>
      <param-value>true</param-value>
    </init-param>
    <!-- ここから追加設定 -->
    <init-param>
      <param-name>trimSpaces</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>genStrAsCharArray</param-name>
      <param-value>true</param-value>
    </init-param>
    <!-- ここまで追加設定 -->
    <load-on-startup>3</load-on-startup>
  </servlet>

この設定をすると、Tomcatが生成するJavaのコードが以下のような感じになります。

// フィールドの宣言に以下のようなcharの配列が追加される
char[] _jspx_char_array_0 = "<html>\n<body>".toCharArray();
char[] _jspx_char_array_1 = "</body></html>\n".toCharArray();

// HTMLを出力する部分のコード
out.write(_jspx_char_array_0);
out.write("Hello world");
out.write(_jspx_char_array_1);

余計な改行やスペースが削除されるのと、charの配列にテキストが抜き出される単位が行単位じゃなくて、静的な部分をまとめてくれるのでメソッドの呼び出しコードが減ります。
これで、とりあえず応急処置・・・。

本当は、コードを分割すべきなんだけどね・・・。

追記(2010/02/17 14:30)

genStrAsCharArrayじゃなくてmappedfileが、JSPの1行をJavaの1行に対応させるかどうかの設定項目らしいので、mappedfileをfalseにするほうがセオリーっぽい。

*1:追記部分にあるようにgenStrAsCharArrayよりもmappedfileを設定するほうがよさそう