🗂

JSPで64K制限に引っかかった時の対処

2021/07/08に公開

現象

JSPでたくさんの項目を表示する場合、The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit Stacktraceというスタックトレースが吐き出されてエラーが発生する場合がある。
javaには1メソッドのサイズ上限が64KBまでという制限があるが、それに引っかかってしまうためだ。

対応

includeディレクティブを使用して画面を分割するという方法があるが、コードを修正せずに対応したい場合は、_jspServiceメソッドのコード量を削減するためにJSPコンパイラの設定を変更する。

$CATALINA_HOME/conf/web.xmlのサーブレット名jspのサーブレットクラスの初期化パラメータに3つのパラメータを追加する。

<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>genStringAsCharArray</param-name>
    <param-value>true</param-value>
  </init-param>
  <init-param>
    <param-name>mappedFile</param-name>
    <param-value>false</param-value>
  </init-param>
  <init-param>
    <param-name>trimSpaces</param-name>
    <param-value>true</param-value>
  </init-param>
  <load-on-starup>3</load-on-startup>
</servlet>

説明

名前
genStringAsCharArray true
mappedFile false
trimSpaces true

jspからjavaコードに変換された_jspServiceメソッド中には大量のout.write("ほげほげ");が出力されている。genStringAsCharArray = trueでは、この"ほげほげ"という文字列リテラルを静的なchar配列として外出ししてメソッド内の容量を下げる。なので、長ったらしい文字列リテラルがたくさんある場合には有効であると思われる。
また、

  out.write("ほげほげ");
  out.write("ふがふが");
  out.write("ぼりぼり");

と複数行に別れているが、mappedFile=falseにすると1行にまとめてくれる。

trimSpacesは余計なスペースや改行を出力せずに圧縮してくれる。

ぎりぎり壁にぶち当たったのであれば、この対応で抜けることができるかもしれない。試して見る価値はある。

web.xmlを変更したらtomcatを再起動して変更を反映させる。

Discussion