minimize

事業拡大のため、新しい仲間を募集しています。
→詳しくはこちら

JSPが生成するサーブレットクラスについて解析します。
今回対象としたのは、Tomcat5.0.27(Windows版)です。

基底クラス

まず、JSPから生成されるサーブレットクラスは HttpJspBase のサブクラスになります。
クラス名は、JSPファイル名とほぼ同じです。
ただし、ピリオドはアンダースコアに変換されます。
例えば、test.jsp というJSPファイルならば生成されるクラス名は test_jsp となります。

HttpJspBaseHttpServlet のサブクラスです。
大した処理はしていないので省略します。
リクエストが来ると、_jspService メソッドを呼び出します。
これが各サーブレットクラスのエントリメソッドとなります。
このメソッドに渡されるパラメータは
HttpServletRequestHttpServletResponse の2つです。

共通処理

サーブレットクラスの _jspService メソッドには、共通処理として
いくつかのロジックがあります。以下、そのロジックを順番に解析します。

JSPファクトリの取得

JspFactoryのstaticフィールドからインスタンスを取得します。

コンテンツタイプの設定

response.setContentType を実行します。
これは、JSPに記述した page 要素の contentType 属性の値になります。
例えば、JSPに

<%@ page contentType="text/html;charset=EUC-JP" %>

という記述があった場合、

response.setContentType("text/html;charset=EUC-JP");

というロジックが実行されます。

PageContextの取得

これが一番大きい処理となります。
先程取得したファクトリのメソッドを実行します。

_jspxFactory.getPageContext(...);

さらに内部を追ってみます。
初回のリクエスト時、PageContextのインスタンスは存在しないので生成されます。
リクエストが完了するとこのインスタンスはファクトリ内にプールされ、
以降のリクエスト時にはこのインスタンスが使い回されることになります。
このプールインスタンスは全JSP共通(つまりTomcat内に唯一)です。

同時に複数のリクエストがあった場合は、
再びPageContextのインスタンスが生成されプールに追加されます。

いずれの場合でも、リクエストの度にPageContextの初期化処理が実行されます。

PageContextの初期化

デフォルトのJSPでは、まずHTTPセッションが生成されます。
page 要素の session 属性を記述することにより、この処理を抑制できます。

<%@ page session="false" %>

これにより、セッションが生成されなくなります。
ソースを追っていけば解りますが、セッションの生成は意外と重い処理です。
そして、セッションはTomcat上で一元管理される為
存在するセッションの数が増える程にセッション関連の処理は遅くなります。
よって、必要の無いセッションは出来る限り生成しない方が良いのです。

次に、JspWriterの生成と初期化を行います。
JspWriter は PageContext のインスタンスと1対1対応で生成されます。
JspWriter が生成されるのは PageContext が生成されるときだけで
後は初期化処理のみが実行されます。
JspWriterの出力バッファは、デフォルトで8kbです。
バッファサイズは page 要素の buffer 属性の記述により変更できます。

<%@ page buffer="128kb" %>

前述したように、PageContext はメモリ内にプールされるので
JspWriter(と出力バッファ)もメモリ内に保持されることになります。
無駄に大きいバッファサイズの指定はメモリを圧迫する事になるので注意しましょう。

後処理

共通処理が終わると、JSP固有のロジックが走ります。
それが全て完了すると、後処理として PageContext をプールに戻す処理が実行されます。
以上でサーブレットクラスの処理は完了です。