再現できる最低限まで削っていったら、めちゃくちゃシンプルで誰でも書いていそうなコードになりました。
びっくりします。ローカル変数の定義順を変えると挙動が変わるところが一番のみどころです。
こんな感じです。Tomcat5.5.17+Java6 b105で確認してます。
5回くらいリロードすると結果が変わります。
最後の空ループの回数を少なくすると、現象が発生するまでのリロード回数が変わります。
package servlets; import java.io.*; import javax.servlet.http.*; public class ProblemServlet extends HttpServlet { protected void doGet (HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); boolean brk = true;//preと順番を逆にすると再現しない boolean pre = false; for(int i = 0; i < 3; ++i){ int j = 0; while(j < 1){ ++j; System.out.println("ループ先頭: " + pre); if(i == 0){ pre = brk; brk = false; System.out.println("continue:" + pre); continue; } if(i == 1) brk = pre; out.println(i); if(brk) out.println("<br>"); } } for(int i = 0; i < 1000; ++i); out.close(); } }
変数preはif(i == 0)の中でしか変更してないので、「continue」の後の「ループ先頭」での値は必ず同じになるはずです。
でも、結果が変わったときには、continueしたあとでpreの値が変わっていることがわかります。
whileを通常のfor(int j = 0; j < 1; ++j)の形にすると再現しません。continueの処理がくさいです。
こんだけ最適化したことでプログラマとしての満足感が得られてしまったので、バグデータベースへの報告はたぶんかなり後回しになると思います。もしそういうのが得意な方がいらっしゃったら、代わりに報告していただけるとありがたいです。こんだけ簡単なコードで再現するので、すでに報告されているかもしれません。