JDKのバグと思われる現象の再現コード

再現できる最低限まで削っていったら、めちゃくちゃシンプルで誰でも書いていそうなコードになりました。
びっくりします。ローカル変数の定義順を変えると挙動が変わるところが一番のみどころです。


こんな感じです。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の処理がくさいです。
こんだけ最適化したことでプログラマとしての満足感が得られてしまったので、バグデータベースへの報告はたぶんかなり後回しになると思います。もしそういうのが得意な方がいらっしゃったら、代わりに報告していただけるとありがたいです。こんだけ簡単なコードで再現するので、すでに報告されているかもしれません。

プログラム言語の次の5年

スクリプト言語、正確には動的型言語が復権しました。でも、静的型言語も健在です。
そして、これからは、Java6でJavaScriptが標準で動くようになったことからもみんなが感じているように、静的言語と動的言語を組み合わせて使うことが当たり前にになります。
組み合わせるというよりは、静的言語の上で動的言語が動くようになるのです。ライブラリはJava、アプリケーションはJavaScript(Rhino)やJRubyという具合にです。
これは、ネイティブコードの上にVMという層ができたように、静的言語と動的言語という層が新しくできるということです。
使い分けとしては、大域的なものを静的言語、局所的なものを動的言語という感じになります。
フレームワークコンポーネント、ライブラリのように大域的でパフォーマンスや信頼性が求められ、仕様が比較的安定するものは静的言語が適しています。
アプリケーションの画面や処理のように局所的で他に影響を与えず、パフォーマンスや信頼性もそれほど求められず、そして仕様が安定しないようなものは動的言語が適しています。


ここまでは、すでに実用化されている話です。問題は、このあとのことです。
まあ、ありきたりなことが起こるはずです。
つまり、動的言語と静的言語の融合です。
Java7で噂されているのは、動的言語に対応したバイトコード仕様ですが、Java言語自体に動的機構が追加されるわけではありません。
これがJava8が噂されるころには、すでに現場で使われているであろうJava6での動的言語と静的言語の使い分けを考慮して、Java7の動的言語対応の実装をふまえた言語拡張が考えられはじめていると思います。
一方で、Rubyなどの動的言語の中にタイプセーフ機構が盛り込むものが出てくると思います。もしかしたら、すでにその動きは始まっているのかもしれないですが。
そのとき実際に実用になるのは、いままで誰もみたことがないような言語機構になるかもしれません。
で、その実装としては、Javaの例で言えば、ひとつのソースコードからJavaバイトコードと動的Javaスクリプトコードを生成するようなものになるかもしれません。


とにかく両方ひとつのソースで書きたいんです。

ゲーデルからプログラマへのメッセージ

ゲーデル不完全性定理からわかることは、すべてのプログラムの正しさを判定できるようなプログラムは存在しないということでした。
また、コンピュータが発展したとしても、すべての問題を解決するプログラムを組むことはできないということもわかりました。
プログラムの自動生成が熟成するとプログラマの仕事がなくなってしまうと考えられていることもありましたが、そんなことはありえません。
いつまでもプログラマの仕事はあります。


それでも、ある程度の枠組みが完成すれば、残っているのは退屈なプログラムだけになっていると考えるかもしれません。
「新しいプログラム」というものはなくなるのではないかと心配になるかもしれません。
でも、ゲーデル不完全性定理が数学を終わらせたわけではなく、新しい数学の始まりになったように、現在開発されている技術が完成すれば、新しい技術の始まりになります。
つまりは、いつの時代でも「新しいもの」はあるということです。


ゲーデル不完全性定理は、技術が完成することはないと言っているわけではありません。ゲーデル不完全性定理が言っていることは、固定した技術ではすべてをまかなえず、常に新しい技術を追い求めないといけないということです。
プログラマは、常に新しいものを追い求めないといけないし、その余地は常にあるということです。
ゲーデル不完全性定理は、プログラマにとって、「新しいもの」が尽きる不安を感じる必要などなく、安心して「新しいもの」を追い求めればいいというメッセージです。