2006年5月31日 のアーカイブ

Java

2006年5月31日 水曜日

研修で、Cの次はJavaについて学んでいる。
Javaは、Virtual Machineというメカニズムを用いて、コンパイル後の仮装機械語を一命令ずつ解釈して実行するというもの。
コンパイラと違って実行ファイルが環境依存にならず、インタプリタと違って文法エラーは事前にチェックできるという優れもの(とほめてみる)。

が、仕様がちょっと気にくわない。

1)forの拡張書式

List array = new ArrayList();
for(String s: args)
{
array.add(s);
}
for(String i: array)
{
System.out.println(i);
// 実行時にConcurrentModificationException例外を食らう。
// System.out.println(” Removed ” + array.remove(array.size() – 1));
}

for(int i = 0; i < array.size(); i++)
{
String s = new String(array.get(i));
System.out.println(s);

//こっちは正常
System.out.println(” Removed -> ” + array.remove(array.size() – 1));
}

ほぼ同じコードだが、配列の要素数が動的に変化すると例外を吐いて終わってしまうのが前者のコード。バグがあるけれど、そこはアルゴリズムでいくらでもフォローできるのが後者のコード。
BASICとかCOBOLとかで育ったプログラマは前者がいいのかもしれないけど、アセンブラとかCで育った私に前者は許せない。
インタプリタゆえ高速化が必要なのかもしれないが、それだったら素直にコンパイラで最適化しろと言いたい。

2)デストラクタ? ファイナライザ?
メモリ領域の問題。
メモリを正しく解放しないと、使用するメモリの量がどんどん増えていってしまう問題をメモリリークといい、サーバ関連のプログラムでは大問題になっている。クライアント関連では、ラグナロクオンラインクライアントの「BattleMode」バグは記憶に新しいところだ。
CやC++ではメモリ領域はプログラマが管理することになっており、あらゆる終了ルールに対してメモリ解放を行うべきという、高いプログラミングスキルを要求する。
それに引き替え、Javaは使わなくなったと判断したメモリ領域は勝手に開放する(ガーベジコレクション)ので、メモリ管理はかなり楽になる。
……と、これだけ聞くとJavaがすばらしいように感じるが。
C++には、あらゆる終了ルールに対して、たった一カ所メモリ解放を行えばいいという特別な場所がある。
クラスの「デストラクタ」メソッドである。
ここ一カ所だけで正しいメモリ管理関数を書いておけば、オブジェクト指向に従ったプログラミングに対してはメモリ管理が正しくできるという寸法だ。応用として、ファイル・ネットワークなどのリソースも同じ方法で管理できる。
C++にある、こんな便利な機能がJavaにないわけがなく。
Javaにも、やはり「ファイナライザ」というメソッドがある。

……が、「デストラクタ」「ファイナライザ」が正しいと仮定した場合、ここでJavaのメモリ管理機能が裏目に出る。
C++のデストラクタは、インスタンスが消えた瞬間に、確実に呼ばれる。ここで終了処理を行わないと、いつまでたってもメモリなどのリソースが解放されないからだ。
しかし、Javaのファイナライザの場合、インスタンスが消えても、実体が残っている限りはファイナライザが呼ばれるとは限らない。ガーベジコレクションがあるため、プログラム終了時あるいはガーベジコレクションが呼ばれるまでの「どこか任意のタイミングで」ファイナライザを呼べばいいだけの話になるからだ。

要するに、C++のデストラクタに比べ、Javaのファイナライザは動作が「読めない」という致命的弱点があるのだ。
これでは、せっかくの機能も宝の持ち腐れというものだろう。プログラマーレベルで最適なコードを用意するという、プログラミングの最高の喜びが手に入れられないのはあまり気にくわない。

ただし、あまり良くないコードに対しては確かに有効なわけで、どちらがよいのかは、プログラマーの「時間」と「自信」次第なんだろうなぁ、とか思ってみたりする。

3)JavaのフルコンパイラとかC++のVMとかないの?
C++のVMに関しては、ヨタ話程度には話があがっているようだが、Javaのフルコンパイラは検索にかからない(前処理コンパイラがばんばん検索にかかるので見つからないだけかもしれないが)。

C++のVMができたら、Javaが不要になるというわけでもないんだろうけど……どこかまじめに研究してくれないかなぁ。