dynamic/static

via L'eclat des jours

航海日誌コメント欄にて、動的束縛の危険性とReturn to COBOLを叫ぶ人、nminoruさんの発言より。

個人的には動的束縛言語は大規模開発に向かないし、Java ですら大規模開発にはむかないと考えています。向かないと信じる理由はデバッグの容易性です。ランタイムが動的になればなるほどデバッグが困難になっていくと思うのです。

Java であろうが Ruby であろうが上物のプログラムだけでなく下で動いているランタイムまでまとめて面倒をみなくてはならなくなるパターンがあります。そして規模が大きいところほどそういう責任を要求されるし、規模が大きいシステムほどランタイムのバグを出しやすいと。
プログラムのバグなのかランタイムのバグなのか切り分けられればいいのですが、そうでないエラーもあります。そうなると OS の底から見上げると JavaRuby もただの1つのプロセスに過ぎないわけで、残るのはコアイメージだけです。
コアイメージを貰って帰ってそこから自分のプログラムが悪いのか、ランタイムが悪いのかを検証する作業になると、言語やシステムの「動的さ」が効いてくるはずです。

一例をあげると、多くのインタプリータが C/C++ で実装されているわけですが、命令のディスパッチルーチンは switch 文を回す形で実装すると思います (普通の C コンパイラは switch 文を適当な大きさのテーブルジャンプに展開します)。Sun の Java VM の場合、いわゆる Classic JVM はそういう実装になっています。これが静的なコードの世界です。

ところが JDK 1.3 から導入された HotSpot VM の場合はこういうディスパッチャーがソースコード上にありません。
どうしているかというと JVM 内にマクロアセンブラとディスパッチャーのテンプレートが入っていて、JVM が起動されるとテンプレートをアセンブラして、毎回 ディスパッチャーコードを生成します(だから起動が遅い)。

これは JVM を起動した CPU 種類(Pentium3/4/SSE2/SSE3)に応じて使用する命令を変えたり、
JVM が起動後に確定してしまうパラメータ(条件フラグ、Java ヒープの最大領域の開始・終了アドレスとか)を命令の即値フィールドに埋め込んだり、フラグを見て if で処理を分けるというような条件分岐命令を減らしたりするためにやっています。

switch 文でディスパッチルーチンを書くよりエレガントな方法ですが、デバッグは面倒になります。
HotSpot VMJavaバイトコードをインタプリートする箇所をデバッガで追っても、シンボルはほとんど見えません。

実際にはこれにスタックフレームの処理、実行時プロファイルの採取、JIT コンパイラ、Safe pointing or Code patching、On stack replacement、最近ではコンカレント GC が加わりますんで、内部の挙動は凄まじく流動的です。

なんかアクセント位置が変(インタプリータ)だが言っていることは真っ当だ。

動的機構は、使い手には利便性が高い。リスク許容度と抱える技術者の製品知識(あるいはベンダーとの関係)に比例して使うべき。
しかし、「リスクを過小評価するな」というのが上の人の言い分だ。