ようになんにもしないのが悪いのでせうか ? それでは , なにか中身のある実行文を書い てみましよう , 次のように while( ! eSwitch ) + + i ; 〃無意味な式文 こんなことをしても , 黄色いボタンがピ ンクのボタンに変わるという目的は実現し ません。黄色いボタンをクリックしても , 黄色いままです (Fig. 5 ) 。 ローカル変数を複数個参照するこんな式 C 言語フォーラム 137 Fig. 7 javap ー c の出力 ( 4 ) : Etest. java の main ( ) # 23 <Field bo 引 ean eSwitch> / / それを a へストアする ( 結果 : a=b;) / / b をオペランドスタックのトップへ Fig. 6 javap ー c の出力 ( 3 ) . 無意味な式文の場合 ( その 2 , 抜粋 ) 18 ifeq 13 15 getstatic istore—l 13 iload-2 10 go セ 0 15 14 Method void main( java. lang. string[ ] ) 6 invokevirtual # 12 <Method int read( ) > 3 getstatic # 9 く Fie ld java. 土 0. InputStream in> //System. in は static 0 goto 3 9 dup 10 土 s セ 0 て e ー 1 11 bipush 98 13 if—icmpne 3 / / 読んだ文字を 2 個作り / / その一つを変数 ch へポップ / / ' b ' をオペランドスタックへ ( 98==ASCI I ' b ' ) / / ch ! = ' b ' なら 3 へ行く ( 実際は ch を無視 : 本文参照 ) 文では ? : int a = 0 , b = 0 ; while( ! eSwich ) 出します。 ます。すなわち , 何らかのメソッドを呼び 中で実行の流れを一時的によそへ移してみ を試みているわけですが , 今度は while 節の 理由が分からないまま闇雲にいろんなこと 空文ループがどーしてだめなのか , その but, why?? メソッド呼び出しなら OK , があるのであった ! この点に実は , 今回のドジの大きな伏線 コンパイラではない ? んけ。 ・・ぬぬぬ , すると javac はワンパス ちょこざいな ! ch なんて結局使わんや ップする ) からです。 使用する ( オペランドスタックから計 2 回ポ 変数 ch への代入と if 命令による比較の計 2 回 ッドの返し値を複製しているのは , それを , ランドスタックのトップにある read() メソ お , 9 番のところで dup 命令により , オペ 造にとくに変わった点はありませんね。な この Etest.java でも , ループ部分の処理構 これも参考のために見ておきましよう (Fig. 7 ) 。 んなハ 4 コードになっているのでしようか ? 見た , " 普通の " ケースの空文ループは , ど さきほど , Etest.java というプログラムで しかし , これもやはりだめです (Fig. 6 ) 。 16 getstatic # 10 <Fie ld java. 土 0. PrintStream out> ldc # 1 く string nwe 're gonna exit now. ” > 21 invokevirtua ー # 11 く Method VOid print ln( java.lang. string)> 24 go セ 0 28 27 POP return 28 19 from tO target type Exception tab : 0 24 <CIass java. iO. IOExcepti011> クラス EmptyTest の中に static void nop() { } という無内容のメソッドを作って , それを 呼び出してみます : while( ! eSwitch ) nop();//static メソッドを呼び出す しかし , これまただめでした。 javap の出 力は Fig. 8 です。 static メソッド ( クラスメソッド ) ではなく て , ランタイムに作られる ( instan ⅱ ate され る ) オプジェクトに伴って動的に配置される メソッド , すなわちインスタンスメソッド ならどうでせうか ? void nop() { } //non-static なメソッド これを while 節の中で呼び出します : while( ! eSwitch ) nop() ; ″インスタンスメソッドを 〃呼び出す どうせこれもだめだろう ? ところがところが ! これでついにピン クのボタンが出現したのであります (Fig. 9 ) 。これまでと , どこがどー違うんでしよ うか ? Fig. 9 の jav 叩の出力を見るかぎり , これ までととくに変わったところはありません ねー現在のメソッド ( カレントメソッド ) は main() です。そのローカル変数としてオ プジェクトがあり , そのオプジェクトのメ ンバを参照するときには 11 番のように aloa d_n 命令がまずあって , それによりオプジ ェクトの参照をオペランドスタックに乗せ ます。 aload ー 1 は , カレントメソッドの最も 冒頭のローカル変数を操作します。 JVMS を見ると , メソッド冒頭で宣言される第一 ローカル変数をオペランドスタックに乗せ る命令は aload ー 0 のはずですけど , 実際は al oad ー 1 が使われています。 aload ー 0 は一体何 を運ぶのか ? 理由は依然として ? ? でありますが , と にかく「 static メソッドはノー ! 」「インスタ ンスメソッドは OK ! 」でありました。それ では , 自クラスではなくてほかのクラスの static メソッドはどうでしようか ? java. la ng. Thread クラスの static メソッド sleep ( ) を while( ! eSwitch ) { 呼んでみましよう :
Thread. sleep( 10 ) ; 〃 1 / 100 秒 } catch ( lnterruptedException e ) { } Thread. sleep ( ) は static メソッドであるに も関わらず , この場合も OK でした。黄色 いボタンをクリックすると , ちゃんとピン クのボタンに変わります。 jav 叩の出力で JVM のコードを見てみまし よう (Fig. 10 ) 。 Thread. sleep() の呼び出し では例外処理があるため , JVM のコードは やや複雑になっています。それを見て見ぬ ふりをすれば , 11 番で sleep ( ) メソッドの引 数である 10 ( 即値 ) をオペランドスタックに 乗せてから , 14 でメソッドを呼び出し , while 節の条件である eSwitch のチェック ( 24 番 ) へ と進んでいます。これも , これまで見てき た JVM コードと構造はまったく同じ , とい えるのではないでしようか。 どーも匂うのは , 「最適化 ( オプティマイ ゼーション ) のバグではないか ? 』という JV M の実装状況です。機械的画一的な最適化 をやっているために , これまでビンクのポ タンに変わらなかったほうのコードでは , 真面目にいちいち毎回 , 変数 eSwitch を参照 ~ フェッチせず , どこか ( たとえば実プロセ ッサのレジスタのどれか ) にキャッシュし ておいた eSwitch の初期値 (=false) をループ の各回で参照しているのではないか ? Java のソースを JVM コードに変換するコ ンパイラは・・・・・ Sun の JDK の場合・・・ ・・ Javac Fig. 8 javap ー c の出力 ( 5 ) : クラス内の static メソッド nop ( ) を呼び出した場合 ( 抜粋 ) 8 go セ 0 14 11 invokestatic # 25 く Method VOid nop( ) > 14 getstatic # 23 く Field boolean eSwitch> 17 ifeq 11 ( 中略 ) Meth0d vo id nop ( ) 24 getstatic # 25 く Field b0 引 ean eSwitch> 21 go セ 0 24 20 POP 17 goto 24 14 invokestatic # 32 くセ hod void sleep(long)> ldc2—w # 34 <Long 10 > 8 go セ 0 24 Fig. 10 1 0javap ー c の出力 ( 7 ) : クラス外 static メソッドを呼んだ場合 ( 抜粋 ) 18 ifeq 11 15 getstatic # 23 く Fie ー d b00 lean eSwitch> 12 invokevi て tual # 25 く Method VOid nop()> / / その参照からメソッドにアクセス 11 引 oad-l / / オブジェクトの参照をオペランドスタックへ乗せる 8 goto 15 Fig. 9 javap ー c の出力 ( 6 ) : インスタンスメソッド nop ( ) を呼び出した場合 ( 抜粋 ) 0 return //return 命令しかないメソッド 11 ( 中略 ) 27 ifeq 11 Exception tab : from tO target type く C lass 11 17 20 138 C MAGAZINE 2000 6 ] ava . ー ang ・ I nterruptedExcept 土 on > ですが , JVM コードを実プロセッサのコー ドに翻訳するコンパイラを仮にここで VMC 君と呼びましよう。、爪åC 君はたぶん , 1980 年代に流行したオプティマイジングコンパ イラ ( 最適化を積極的に行うコンパイラ ) の 流儀で仕事をするのでしよう。 オプティマイジングコンパイラもたかが コンパイラ , たかがコンピュータブログラ ムですから , ソースコードの表面的な部分 しか見ません。その小賢しくも愚かな VMC 君の目が EmptyTest. main() のソースを見た かぎりでは , eS 忙 h の値にアクセスしてか ら次にアクセスするまでの間に , eSwitch の 値が変えられそうな部分がないではありま せんか ! 「よし ! これは最適化できる ! 」と VMC 君は喜び勇んで判断します。そこで , JVM のコード ( これが VMC 君にとってのソース 表を久しぶりに調べますと , なんと ! Java ・・と思いつつ , Java のキーワードー覧 同様の修飾子があるとええなぁ・・ です。 volatile = 最適化の禁。 JavaÄ語にも けないぞというコンパイラに対する " 牽制 ' 変数でも , そう思い込んで最適化してはい その後アクセスされていないように見える それは , ソースの中で最初に登場後 , という修飾子を導入しました。 ることを認め ( 諦め ) , ISO/ANSI C に volatile ラというプログラムの " 知能 " にも限界があ のバグをとっくに経験しており , コンパイ 豊富な C プログラマは , このような最適化 Java プログラマに比べると桁違いに経験 あった ! Java にも低レベル修飾子が れていることが分かりません。 ンドラの中で・・・・・・ eSwitch ( ) の値が変えら で・・・・・・たとえば割り込み処理 / イベントハ main ( ) の流れを見たかぎりではどこかよそ まうのです。 JVM コードのレベルでも , シュし , それを毎回のアクセスで使ってし わらず , VMC 君は初期値をどこかにキャッ eSwitch の値を get せよと書いてあるにもかか プログラムである ) にはループの各回で
であるはずです。 Java の boolean タイプの fal se という値は , JVM の上では整数 0 によって 表現されます。 次の 14 番の ifeq 命令は「オペランドの値が ゼロならば〇〇へ行け」という条件分岐命令 Method void main( java .lang. string[ ] ) Fig. 1 javap ー c の出力 ( 1 ー a ) . 単なる空文の場合 です。 そこで 14 番の ifeq 命令によって , eSwitch が false ならば 11 番へ行き , 再び eSwitch の現 在値をオペランドスタックにコピーします。 それまでの間にボタンがクリックされ , Emp 0 new # 5 <C ー ass EmptyTest> 3 d 叩 4 invokespecial # 16 <Meth0d EmptyTest( ) > 7 astore—l 8 goto 11 11 getstatic # 23 く Fie ー d b00 lean eSwitch> 14 ifeq 11 17 引 oad—l 18 getfie ld # 22 く Fie ld javax. swing. JButton button> 21 getstatic # 25 く Field java. awt.CoIor pink> 24 invokevirtual # 26 く MethOd void setBackground (java. awt.CO lor) 27 引 oad—l 28 getfield # 22 <FieId javax. swing. JButton button> ldc # 4 く string ”終わりは脱兎のごとし 5 44 40 31 33 invokevirtual # 28 く Method void setText ( java .lang. String) > return 41 invokevirtua ー # 27 く Method void setEnabl ed(boo lean)> iconst—l 37 getfield # 22 <FieId javax. swing. JButton button> 36 引 oad—l Fig. 2 eSwitch をインスタンス変数にした場合 ( 空文による wh ⅱ e ループ , 抜粋 ) 8 goto 11 11 引 oad—l / / オブジェクトの参照をオペランドスタックに乗せる 15 ifeq 11 8 goto 11 11 getstatic 14 ifeq 11 8 go セ 0 11 14 ifeq 11 Fig. 5 javap 10 go に 0 16 13 iinc 11 16 getstatic 19 ifeq 13 Fig. 4 javap ー c の出力 ( 1 (C) : 空プロックの場合 ( 抜粋 ) # 23 <Fie 旧 boolean eSwitch> 2000 6 ー c の出力 ( 2 ) 11 getstatic # 23 <Fie ld b00 ー ean eSwitch> # 23 <Fie ld b00 lean eSwitch> 無意味な式文の場合 ( その 1 , 抜粋 ) 136 C MAGAZINE 12 getfield # 23 く F 土引 d boolean eSwitch> / / そのフィールドの値を乗せる Fig. 3 javap ー c の出力 ( 1 (b) : continue 文の場合 ( 抜粋 ) / / オペランドスタックのトップがゼロなら 11 へ行く tyTest.java の 41 行目の , EmptyTest. eSwitch = true, が実行されていたならば , ifeq 命令の条件 が偽となり , 実行は while ループを脱けて次 へ進むはずです。 ではでは , なぜ , 現状の EmptyTest プロ グラムでは , 黄色い " 初めは処女のごとく " ボタンをクリックしたとき , それがピンク の " 終わりは脱兎のごとし " ボタンに変わら ないのでしようか ? なお , 今回のお話はもつばら Wmdows95 の上の JDK 1.2.2 for Win32 が " 事故現場 " で す。 Sun からの JDK 1.2.2 for Linux は GUI 環 境として KDE / VM を前提としており , 私 の GNOME/EnIightenment の上では正しく 動作しません。この linux 向け JDK は , スレ ッドが green threads ( J 、爪 4 側で実装するスレ ッド ) のみ , JIT コンパイラなしとなってい ます。一方 , 3 月下旬に発表された BIackdown の JDK 1.2.2 for Linux RC4 は , native threads ( OS のスレッド機構を使用するスレッド ) と sunwjitJIT コンパイラを提供しています。 フラグ eSwitch を static フィールド ( クラス 変数 ) ではなく , 動的フィールド ( オプジェ クトの変数 , インスタンス変数 ) にしてみた 場合には Fig. 2 のようなコードになり , 実行 結果は同じです ( Fig. 2 ~ 10 の〃で始まるコ メントは , すべて本稿の筆者が後で記入し たものです ) 。やはりピンクのボタンは出現 しません。なお , このように eS tch をオプ ジェクトの変数にした場合には , アクショ ンリスナのコンストラクタ引数として Emp Test オプジェクトの参照を受け取る , そ の参照から eS ⅶ tch にアクセスする , といっ た書き方が必要です。 空文がだめなら , con ⅱ nue 文はいかがで せうか ? しかし結果は , 空文のときと同 じでした (Fig. 3 ) 。 ほなら , 空文でも continue 文でもなく , 空プロック , while( ! eSwitch ) { } はいかがでせうか ? これまた結果は , 空 文の場合とおんなじです ( Fig. 4 ) 。 これはもしかして , 空文や空プロックの
うメソッド , および自己クラスのコンスト >javacc. bat Kantan. jj と記述すれば , 作られるルーチンは大文字 とすると , Fig. 1 に示す七つのファイル群 ラクタを使っているが , これらは JavaCC が自動生成される。このなかにある Kanta 小文字の別を無視するようになる。 が作成するものを利用しているのである。 n. java が , 解析プログラムの中心となるク List 1 ではオプション部をコメントアウ 規則部 ラスが記述されたソースファイルである。 トしている。なお , LOOKAHEAD の意味 規則部には , 字句定義と生成規則がある。 そしてこれを , については後述する。 実際にはそのほかにもあるが こでは基 >javac Kantan. java Java コンバイルユニット部 とコンパイルすると , 実際の式解析プログ 本的なことのみを説明する。 PARSER_BEGIN ( クラス名 ) から PARSE List 1 では 22 ~ 25 行の「 SKIP: 」と書いてあ ラムができあがる。このプログラムの動作 は Fig. 2 のようになるので , 試してほしい。 R_END( クラス名 ) で囲まれた部分に , Java るプロック , および 27 ~ 30 行 , 32 ~ 35 行の のコンパイルユニット ( すなわちクラス定 「 TOKEN : 」と書いてあるプロックが字句定 文法定義ファイルの内容 義 ) を記述する。一般的には , 義の部分だ。 PARSER_BEGIN( クラス名 ) SKIP のプロックでは , 読み飛ばす字句 class クラス名 { を指定する。コメントや空白文字のように あれば読みやすくはなるが , 文法上必要な いという字句を無視するために使う。 PARSER END ( クラス名 ) TOKEN のプロックでは , 正規表現によ という形になる ( それぞれのクラス名は同 って字句 ( トークン ) の記述を行う。正規表 じにする ) ー記述されたクラスに 現といっても grep などで使う正規表現とは 0 ( ー、一ロ JavaCC が作るメソッドが付加されて , 解 文法定義ファイルの例 ( Kantan. jj ) 析用のクラスができるのだ。 List 1 では main ( ) のなかで , shiki() とい Fig. 1 JavaCC が作るファイル Kantan. j 〕 Kantan. j ava KantanTokenManager. 〕 ava TokenMgrError. java ParseExcept i on. j ava TOken. java ASC I I —CharS tream. j ava KantanConstants. java 前述のように パーサジェネレータとい うものは , 文法を定義したファイルに従っ てテキストを解析するソースコードを生成 するツールだ。 JavaCC の場合 , 文法定義ファイルは , ・オプション部 ( 省略可 ) ・ Java コン / ヾイルユニット音 5 ・規則部 から構成される。 これらについて , 解説し よう。 オプション部 文法定義ファイルの先頭にある , options{ がオプション部である。このなかに動作に 関するオプションを記述する。 たとえば , options{ IGNORE CASE = true; Fig. 2 List 1 の動作 > j ava Kantan 12 * 34 十 56 * 78 く一一一一一入力 accept > j ava Kantan 12 * 34 十 56 十 78 ぐーーー入力 reject ParseException : Encountered ”十” at line 1 , column 9 . Was expecting: List 2 : options{ L(X)KAHEAD = 3 : 6 : 7 : PARSER—BEGIN ( Kantan ) 8 : public class Kantan{ public static VOid main(string[ ] args) { 9 : Kantan parser = new Kantan ( system. in 10 : 11 : try{ shiki ( ); 12 : system. ou セ . printl n ( "accept ” 13 : } catch(ParseException e) { 14 : system. out. p て土 n 凵 n ( "reject" 15 : e. printStackTrace ( 16 : 17 : 18 : 19 : } 20 : PARSER—END ( Kantan ) 21 : 22 : SKIP 23 : { 24 : 25 : } 26 : 27 : TOK 風、・ 29 : 30 : } 31 : 32 : TOKEN ・ 33 : 34 : 35 : } 36 : 37 : void shiki( ) 38 : ( 39 : 40 : } 41 : 42 : void kou( ) 43 : { 44 : 45 : } (JavaCC が生成 ) く EO も : <KAZU : kou() ” + ″ kou() く EO い . generateParseExcept i on ( compil ed COde ) at Kantan . jJ—consume—token(Kantan. java: 120 ) at Kantan kou( Kantan. java : 23 ) at Kantan. shiki (Kantan. java: 17 ) at Kantan. . main(Kantan. java: 6 ) at Kantan く KAZU> ″ * ”く KAZU> 146 C MAGAZINE 2000 6
プログラミングレッスン 3 a 言語 マ早クーー、 言語を始めよ のような修飾子を導入するのです。この修 にも vola ⅱ le があるではありませんか ! そ 飾子の意味は , 「この変数に関しては最適化 うだよなー なんといっても Java 言語のべ コンパイルをしてもよい / してください」と ースは C / C + + だから , あって当然か・・・・・・ いう指示です。あるいは javac/java に最適化 というわけで , 今回の Java の空文の一件 オプションがあってもよいでしよう。今の は急転直下 , アンチクライマックスの解決 プロセッサとメモリは結構高速ですから , デ とあいなりました。 List 1 の EmptyTest.java フォルトを「最適化なし」にしても通常の実 の状態 , すなわち while 節の実行文が空文で 務アプリケーションでは目に見える性能劣 ある状態のままで , 12 行目の変数宣言 化は絶対に生じないと私は思います。 static boolean eSwitch; 最初なぜ私は , Java には volatile がないと を次のように書き換えます。 いう印象でいたのか ? それは , 「 Java は C/ static VO は 1 ⅱ e boolean eSwitch; たったこれだけのことで , めでたく黄色 C + + に比べるとずっと高級な高級言語です から , プログラマに低レベルな注意力を要 いボタンはピンクのボタンへと変わってく 請するような仕組みはもはや存在しないは れるのであります。 、の言語を語めよう a 言語プロ ? ラミイグレッス / 上 ) ずである」という漠然とした気持ちでいたか 問題はあっけなく解決。こうしても jav 叩 らですね。しかもスレッドやイベントハン の出力は前とまったく同じですから , volatile 結城浩犀るプゴグちミゾツネ心名あ ドラをフル活用する Java 言語では , 「この変 への対応は Java バイトコード (JVM の命令 ) = 年めのし語人門書。本を ( 上巻 ) ま、 の知識や経験のない初心者 数がどこかよそで変えられている / 使われて →実プロセッサの実行コードという翻訳過 いるかも知れへん = 最適化はバグにつなが 程で行われていることが明らかです。 る」という状況が非常に多くなっています。 でもなぜ , non-static メソッドや static メ ソッドでもほかのクラスのメソッドの場合 言い換えると C で volatile を使わなくては ならないような特殊な場面が , Java ではど には , この最適化を免れてしまうのか ? ちらかというと一般的な場面です。それに それはおそらく , VMC の実装において , また , いくらコンパイラの知能に限界があ これらのケースでは , 変えられていないよ うに見える変数でも呼ばれたメソッドの中 るといっても , while( ! f00 ) で変えられているかも知れへんから最適化 みたいな節があれば「この f00 の値はいつか せんでおこう , という知恵が働いているの づら どこかで・・・・・・ソース面からは見えない場所 でしよう。 で・・・・・・変えられるのだな」と子どもでも判断 しかしですね , と私はここで声を大にし できるでしよう。変わりうるからこそ , while て言いたい。そもそもプログラムを書いて の条件式になっているわけですよ ! だか 「この変数は volatile にしとか いくときに ら小賢しく最適化をせずに , ループの毎回 んとやばいな」ということを , いちいち , 正 で f 。。を律儀に馬鹿正直にフェッチすべき 確に判断するのはたいへんです。実務プロ なのです。 グラマにそこまで細かい低レベルの注意を 「 Java ではデフォルトで最適化なしにせよ』 求めるのは , 酷であります。 C 言語の経験 という主張には , もちろん賛否両論がある や , オプティマイジングコンパイラの問題 でしよう。でも実務プログラミングにおけ 点に関する知識のない , プログラミングに るユーザプログラミング / ビジネス現場プロ →新から入った初心者プログラマにと Java ロロロ グラミングのすそ野を Java によって拡大す っては , これは尚更のことです。 るためには , 「楽屋裏におけるコンパイラの ですので言語の設計 / 実装方式としては , 仕事ぶりのような , 低レベルの知識や低レ 「デフォルトでは最適化をしない』を貫くの ベルへの注意は要らない」が絶対的な条件 が正解ではないでせうか ? そして vola ⅲ e であるはずです。 とは逆に , 経験豊富なべテランプログラマ そしてむしろ , 最適化をプログラマが必 のための修飾子として , たとえば nonvolatile B5 変 376 ページ ISDN 4-7973-0803-6 本体価格 2,400 円 4 ~ 言語 プロクラミンク をレッスン 0 「ツら羡クトめ 版出劵 オプジクト指向を始めよう Ja 言語プログラミングレッスン ( 下 ) 結城浩著 結城浩によプ朝ツラミング初心者のための ・ Java 言語入門書体書て下巻 ) 、ではぐ上巻 の知識を踏まえ、クラス、クラスの継承例外 , ′スレッド、バヅケツなど、オブジェクト指向 の概念を、多くのサンプルプログラムを使って、 明快に解説しているいーこ B5 変 344 ページ ISDN 4-7973-1 OI 0-3 本体価格 2400 円 好評発売中 ! SOFT ソントバングバブリッシング株式会 BANK 物れP://b00トS. softbank. c 0. jp/ ublishing EL : 03-5642- 白 T00 ~ 示価格は税別 ) C 言語フォーラム 139
TabIe 1 JBu ⅱ de 「 3.5 のバージョンと機能 機能概要 100 % Pu 「 eJava アプリケーション , アプレットの開発支援 Windows/SOIa 「 is/Linux 上で動作 Java 2 プラットホーム対応 Java 2 対応の Just-In-Time (JIT) コンバイラ フラウザ / 工デイタ / デバッガ / コンバイラ / ヘルプを統合 Java 2 (JFC/Swin ) ん avaBeans 対応のビジュアルデザイナ プロジェクト / アプレット / クラスの作成ウイザード JBu ⅱ de 「の開発環境へサードバーティ製ツールを統合できる 0 en T00 API CUA および Emacs キーバインドのサポート Java/lDL/SQL/HTML/JSP/XML/XSL/C + + などに対応した構文ハイライト表示 メンバ / メソッド / メソッド引数 / バッケージ名ん ava 構文の入力支援 構文工ラーの解析 / 表示 ウォッチ / ステップ実行 / ブレークポイント / メソッド末尾までの実行 / 評価 / ステップアウト / ブレークポイン トのロギング / 条件デバッグ デバッガ J 団デバック A 曰に対応 マルチプロセスデバッグ 200 以上の JavaBeans を提供 JavaBeans ソースコード隠蔽機能 基本機能 ( 強化 ) 複数バージョンの JDK を切り替え可能 高速なコンバイラ ダイアログ / フレーム〃 ( ネル作成ウイザード 統合開発環境 ( 強化 ) Java インタフェイス実装 / クラスのオーバライド / 抽象メソッドの実装を支援するウイザード CVS を利用したソースコード管理 / カスタムウイザード / ビューワなどの OpenToo サンプル コード入力支援機能 ( 強化 ) チーム開発用にカスタマイズ可能なコードテンプレート J 団テパッグ A 曰に対応したすべての JDK に対応 デバッガ ( 強化 ) ステップ実行方式のカスタマイズ ツールチップによる評価とカスタマイス可能なコードテンプレート JavaBeans 作成ウイザード プロバティ / イベント / Bea 司 nfo のビジュアル定義 開発した JavaBeans の動作チェック サンプル JavaBeans のソースコード ハ - ドコ - ドされた文字列からリソースファイルを生成するウイザード 複数言語をサポートするリソースファイルの同時編集 国際化対応をサポートするビジュアルデザイナ プロバティファイルの編集支援 複数言語をサポートしたサンプルアプリケーション JA 日ファイル作成ウイザード マ二フェストファイルの自動生成 サーブレット作成ウイザード 内蔵 Web サーバによるサーブレットの実行 JDBC 準拠によるデータベースシステムのビジュアル開発支援 ( DataEx 「 ess) データベース接続 / マスタ・ティテール関係 / ピックリスト / 参照 / 複数テーブルのジョイン / トランザクショ ンなどをサポートするデータアクセスコンポーネント JFC/Swin べースのデータベース対応コントロール SQL 作成 / リソース化支援 モバイルコンピューティングを実現する Pu 「 e Java によるストレージデータベース オプジェクトストレージ / 同時接続性 / トランザクション管理 / SQL -92 準拠のクエリエンジン 詳細なブレークポイント設定 スレッドのテットロック状態の自動検出と検知機能 デバッグ機能 ( 強化 ) 別プロセスで起動している Java アプリケーションへの接続機能 分散アプリケーションのリモートデバッグ サーブレットのデバッグ サーブレット開発 ( 強化 ) サーブレットのテンプレート データベースアプリケーション開発襁化 ) DataEx 「 ess ソースコード JSP 作成ウィサード 内蔵 Web サーバによる JSP の実行 JSP アプリケーション JSP のテパッグ 開発 JSP のテンプレート ショッピングカートシステムなどのサンプル J2EE に準拠した EJB をビジュアル開発 EJB インタフェイスウイザード EJB 1 . 1 の XML 配布ディスクリプタの生成支援 CORBA 2.3 仕様に準拠 / Java 2 完全対応の VisiB 「 oke 「 4.0 の開発ライセンス付属 IDL サンプルウィサード CO 日 BAHTML クライアントアプリケーションウイザード CO 日 BA サーバアプリケーションウイザード 工デイタにおける IDL シンタックス対応 CORB Ⅳ日 M ーによるクレジットカード承認のサンプル Foundation P 「 0 厄 ssion 引版 nterprise 版 〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇 〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇 〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇 基本機能 統合開発環境 工デイタ コード入力支援機能 JavaBeans ( 強化 ) 国際化 アプリケーション配布 サーブレット開発 データベース アプリケーション開発 JDataSto 「 e Ente 「 p 「 ise JavaBeans(EJB) C O 日 BA 対応分散 オプジェクト 142 C MAGMINE 2000 6
情が変わる。 List6 のプログラムでは , クラ ス F00 で定義している bar メソッドの引数の 型がⅲ t であり , クラス List6 で定義している bar メソッドの引数の型が double になってい る。その結果 , Fig. 9 の ( 1 ) は成立するが , ②は成立しない。よって , 「 my. bar ②」の 呼び出しは曖味であり , コンパイルエラー になる (Fig. 11 ) 。 なお , 仮に List 6 のなかに「 my. bar(2) 」の 呼び出しがなく , 「 my. bar ( 2.0 ) 」という呼 び出しのみであれば , これは一意に List6 の bar の呼び出しであると決定できるため , 曖味さはなく , コンパイルは成功すること に注意してほしい。つまり , 曖味な関係に なりえるメソッドが定義されているだけで はコンパイルエラーにはならず , あくまで それを呼び出そうとするコードが存在した 場合にのみコンパイルエラーになる。 このことを強調するために , List 7 を考 えてみよう。このプログラムでは , メソッ ド b の引数がふたつに拡張されている。ク ラス Foo のメソッド bar の引数はそれぞれ do uble と int という型であり , クラス F00 をス ーパークラスに持つクラス List7 の bar の引 数は逆に int と double である。もしもこれら ふたつのメソッドがともに適用可能 ( かっ アクセスも可能 ) と判断されたならば , 両 IS 同名メソッドと引数の関係 return X * y * y; double bar(int x, double y) { 0 lass 土 st7 extends F00 ( return x * y ー double bar(double x, 加し y) class F00 { / * も土 s し 7 * / System. out.println(my. baて()を 2 ) system. out. println(my. bar(), 2.0 ) sy em. ou し p て土 n 凵 n ( my. て ( 2. の 2 ) List7 my = new List7( public s し土 c void main(String[ ] args) { Java プロクラミングリファレンス 詳説 JDK 解体新ロ 者は Fig. 9 のルールに当てはめた場合 , ど ちらも他方よりもより適合することはない と判断できる。 しかし , それが問題になるのは , ある呼 び出しに対してふたつのメソッドがどちら も適用可能であった場合に限定される。 Li st 7 の main メソッドではメソッド bar に対し て三つの呼び出しを行っているが , 最初の ふたつは実引数並びが「 ( 2.0 , 2 ) 」および「 ( 2 , 2.0 ) 」であるため , この場合には一方のメソ ッドのみが適用可能となり , 曖味さは生じ ない。実引数並びが「 ( 2 , 2 ) 」という第 3 の 呼び出しを試みて , 初めてふたつのメソッ ドがともに適用可能になり , その結果 , の行でコンパイルエラーになる。もしも第 3 の呼び出しを削除してしまえば , List7 の プログラムは正常にコンパイルされ , 正常 に動作するのだ。 こでもう一度 List 4 を振り返ってみる と , クラス階層が「 F00 → Bar → Baz → List4 」 となっていて , それぞれで定義されている overloaded というメソッドの引数が , やは り「 double → int → byte ( → char) 」という順序 になっているため , overloaded の呼び出し はすべて曖味さがなく「もっとも適合する」 メソッドが決定できていたのである。この 場合も , クラス階層のなかで実引数の型が 登場する順序を入れ替えて , たとえば Foo の overloaded の引数の型を int にし , Bar の 型を double にすると , コンパイルエラーに なる。 念のために記しておくと , List8 の場合に は , 「 my. bar ②」および「 my. bar ( 2.0 ) 」のい ずれの呼び出しにおいても , 適用可能でア クセス可能なメソッドはひとっしかない。 なぜならば , シグネチャがまったく同じメ ソッドをサプクラスで定義した場合には , スーパークラスのメソッドをオーバライド したことになり , サプクラスのメソッドだ けがアクセス可能となり , 曖味さは生じな いからである。 Fig. 10 List 5 のサンプルラン D : %cmaga*javaref>java List6 8 Fig. 11 List 6 のコンバイル結果 D:*cmaga*javaref>javac L 土 s セ 6. java List6. java:18: bar への参照はあいまいで す。 doub 厄 bar (double) と int bar ( 土 n し ) に 定義されています。 system. out. println (my. bar ( 2 ) ) ・ 工ラー 1 個 / / OK / / OK / / NG 同名メソッドが一般的なオーバライドとなる場合 IS system. out.println(my. bar(2.0)嶹 system. out.println(my. bar(2) / / どちらも、 List8 のてを呼び出す。 List8 my = new List8( public static void main(String[ ] args) ( return X * X * x; double bar(double x) ( c ー ass も is に 8 extends F00 ( return X * x; double bar(double x) ( class F00 { この場合、一般のメソッドオーバライドである。 / * もちろんこのような定義であれば問題ない。 / * List 8 * / Java プログラミングリファレンス詳説 JDK 解体新書 109
特別 記事 = 三五はさまざまなプラットホ を作成するためには , Java 用のバーサジ いま Javaään , ームで実行できるようになり , その理論的 エネレータが必要になる。今回はそのよう なツールのなかから「 Java Compiler CO な言語仕様もあって C 言語と並ぶ基幹言語 としての地位を築きつつある。この Java mp ⅱ e 「」を紹介し , 実際に活用するための 言語を使い , コンバイラそのものやちょっ 手法を解説する。 としたテキストフィルタアプリケーション Java バーサジェネレータの活用 Java CompiIer CompiIer 毛呂宗夫 の SunTest グループによって配布されてい ・字句解析と構文解析が統合されている Java のバーサジェネレータ ・トップダウン型の構文解析をし , LL たが , 現在では Metamata 社が配布を行っ ( k ) 文法を受け付ける ている。 TabIe 1 のアドレスより , 自己解 パーサジェネレータ ( 構文解析器作成ッ 凍クラスファイルの形でダウンロードが可 ・非終端記号をメソッドの形で表す ール ) とは , 「文法定義ファイル」に従って 能 ( 約 800K バイト ) だ。 HTML 形式のドキ ・サンプルとして多数の文法定義ファイ テキストを処理するプログラム , たとえば ュメントもここから入手できる。 ルが付いている。そのなかには C, C コンパイラなどの作成を支援してくれるツ インストール作業には , Java が使える環 + + , Java, HTML さらには JavaCC そ ールである。 C 言語では yacc や bison が有名 境が必要になる。インストーラそのものも のものまである 例を見てみよう。 List 1 は , 「 a * b + c * d Java アプリケーションになっているため ( a ~ d は自然数 ) 」という入力形式のみを受 だ。ダウンロードで入手したクラスファイ Java に対応したパーサジェネレータおよ ル「 JavaCC1-1. class 」のあるディレクトリで , け付ける , 極度に簡単な式解析プログラム びレクサジェネレータは , すでにいくつか の文法定義ファイルだ。実際に値の計算は 存在する (TabIe 1 ) 。本稿ではこのなかか >j ava J avaC C 1 1 せず , 入力の形式が正しいときは "accept ら , 比較的多く使われていると思われる Ja と実行すると , インストール画面が表示さ va Compiler Compiler ( 以下 JavaCC) につい れる。あとはインストーラに従い , 使用条 と表示し , 正しくないときは "reject" と表 示してエラー情報を返す。 て紹介しよう。 件の確認やインストールディレクトリの指 これを Kantan. jj という名前のファイルに 定を行えばよい。 入手とインストール し (JavaCC の文法ファイルは「 . jj 」という拡 張子 ) , JavaCC をインストールした場所の JavaCC はフリーソフトであり , インタ bin サプディレクトリのなかにある javacc. bat ーネットを通じて入手できる。以前は Sun を使って , TabIe 1 Java 用のバーサジェネレータと入手先 名称 文法 インターネット上のリソース http://www.metamata.com/JavaCC/ JavaCC LL(k) Metamata Pa 「 se LL(k) http://www.metamata.com/p 「 oducts/parse_top. html SableCC LALR(I ) http://www.sable.mcgill.ca/sablecc/ http://www.antlr.org/ LL(k) ANTLR http://www.p 「 inceton. edufiappel/modern/java/ CUP LALR(I) http://www.cs.colo 「ado.edu/serl/misc/jb.html http://www.cs.purdue.edu/jtb/ JTB http://www.princeton.edu/¯appel/mode 「 n/java/ JLex 特徴と使用例 JavaCC には以下のような特徴がある。 備考 サポートが Sun から Metamata に変わった Metamata Suite" の一部。 JavaCC の後継ツール GNU ライセンス C + + のコード生成も可 パーサジェネレータのみ Bison, 日 ex の出力を Java に変換するツール JavaCC 用抽象構文木作成ツール レクサジェネレータ 特別記事 Java パーサジェネレータの活用 145
耳むずかしな力あドジりました 第朝回 Java イベントハンドラ とのコミュニケーション 宏 石合 分からの続きです ) 。本誌前号 ( 5 月号 ) を持 文中の "JSL" は , 羽 le Java Language Specifica あらためて Java と C 言語を ⅱ on の略です。本文中で言及する JSL は , 現 っていない読者や , 持っていてもどこかか 比較してみる 在 dr 血が公開されている second edition では ら引っ張りだすのが面倒という読者のため なく , 本になって出版されている stedi ⅱ on に , この話題に関わるプログラムのリスト 今回の枕話は死刑について : を List 1 に再掲します (EmptyTest.java) 。本 です。 死刑制度が殺人犯罪の抑止に役立ってい ないことは明白です。死刑制度は , 人間の 自然な感情 ( 原始的な感情 ) を法治国家が肖 定していることの表れです。ただし死刑の 最大にまずい点は , それによって , 犯人の 死刑を願い実行する個人や集団を“殺人者と 同じ人間レベルに置いてしまう”ことにあり ます。私たちは , 同じく殺す側に立ってし まう。人間の魂が , 人間性が , より高い方 向へと進化していかないのです。 " 殺人犯罪 者を生む思想土壌 " = " 殺しの感情をセープし ない思想土壌 " が , そのまま温存されてしま います。判決に対して「犯人が死刑にならな くて口惜しい」といった感想がおおっぴらに 語られるのは , なんか , ものすごく野蛮な 感じを受けます。その野蛮さは , なにより も , 亡くなったかたの永遠の霊福を大きく 妨げるでしよう。 犯人の処罰をどうするかより , この世か ら犯罪 ( とくに殺人のような凶悪犯罪 ) をな くす方策のほうが何桁も重要です。なぜこ の , より重要なテーマのほうが , ややもす るとマスコミ等の上で影が薄くなりがちな のでしようか ? さて今回のドジ談義は , Java の空文と whi le 節をめぐってのお話です ( 前号の最後の部 1 List EmptyTest. java 1 : / * * EmptyTest. java 2 : * Java の空文の振る舞いを調べる * Mar. 2000 , hiwa( 岩谷宏 ) 3 : 5 : import javax. swing. * ー import java. awt. * ー 6 : import java. awt.event. *ー 7 : 8 : public class EmptyTest extends MyJavaSwingApp 9 : 10 : ( 11 : JButton button; static b00 ー ean eSwitch ー 12 : 13 : 14 : public EmptyTest( ) { super( "EmptyTest" 15 : eSwitch = false; 16 : button = new JButton( ″初めは処女のごとく” 17 : button. addAct ionLi stener ( new Experience ( ) 18 : button. setBackground( C 引 0 て . ye Ⅱ OW 19 : getContentPane ( ) . add ( button , BorderLayout. CENTER 20 : show( 21 : 22 : 24 : public static void main( string args[ ] ) { EmptyTest et = new EmptyTest( 26 : while( ! eswitch ) / / Java の空文 28 : 29 : et. button. setBackground ( COI 0 て . pink 30 : et.button. setText( ”終わりは脱兎のごとし” 31 : et. button. setEnab led ( true 32 : 33 : 34 : } 35 : 36 : class Experience implements ActionListener 37 : { 38 : public void actionperformed( ActionEvent e ) { JButton button = (JButton) (). getsource( ) 39 : button. setEnabled( false 40 : EmptyTest. eSwi tch = true ー 41 : 42 : 43 : } C 言語フォーラム 133
最新国ロロレポ - ト JavaBeans プロバティ作成 Fig. 4 各種デバッグ情報の表示 や system main Signal dispatcher い Thread-O runO : 99. sun amscreenupdater. ScreenUpdater.java ←ト三 nextEntryO . 四 . sun awt.ScreenlJpdater,ScreenUpdater.java &*waitO : 424. 旧 v 引 ang. Ob ct. Object.java ト W tO . -1,java.lang.Object, Objectjava や screen Updater ← 0 TimerQueue ト山 nO 479. java.langThread,Thread.java e-»this={sun.awt.windowsvroolkit@3a1} 9 「 unO. 13 れ sun awtWindows.WToolkit,WToolkit.java ト eventLOOPO : -1. sun.aWt.WindowsMoolkit,Moolkitjava ト runO - 413 , sun awt.PostEventQueue. SunT001kitjava ・ wa 0 : 424.java.lang. Object,Object.java ・ *w 0 : -1. va 」 ang. Ob ct. Ob 山 ava や SunToolkitPOStEventQueue-O AWT-EventQueue-O ・ヨ「リ nO :114,javalang ref.Reference$ReferenceHandler, Reference.java 物引 tO : 424 」 ava 」 ang. Ob は 0 切 ec い a 槌 ←・ W tO :-1. java.lang.Object. Object.java や、 ReferenceHandler Fig. 5 第づロバティの加ー lin き CO 「 、℃ 0 に一 づロバティ ー . ルという プロリィの物 ~ 」 3 COI 研 ーに 3 材 COlor 、しい凵気、 1 ミゴロテン名 : 簡学な説叫 : 新 新 れ日 : n00 日 ま 0 ⅶ onFo 頑 ョ下 0 用 を S “ ノ物により提催 *bu onFO 祺 員 0 ⅶ onF0 キャンセル ヘルプ 更新 0 日 na に師 ることができる (Fig. 4 ) 。 ProfessionaI 版 /Enterprise 版では , ソー スウインドウで変数の上にカーソルを置く とツールチップに値が表示される。 Found ation 版にはこの機能はないが , ウォッチ機 能などで代替できる。また Professional 版以 上はサープレットのデバッグ機能を持ち , Enterprise 版では JSP のテパッグもサポート する。 JavaBeans 開発支援 ProfessionaI 版 /Enterprise 版には , Java Beans , サープレット , JSP, JDataStore , EJB, CORBA などの開発支援機能が含ま れている。このなかから一例として , Java Beans 開発支援機能を取りあげてみる。 初めに JavaBeans 作成ウイザードを用い て Bean の雛形を生成する。プロバティ作 成やイベント設定など , Bean 構築作業の 多くは対話形式で行う (Fig. 5 ) 。 BeanInfo やプロバティエデイタに関しても 編集が可能である。また , GUI コンポーネ ントを配置する場合にはビジュアルデザイ ナが利用できる。 ほかにもアプリケーション , アプレット , サープレットなどのウイザードが準備され , Bean の検証用ツールである "BeanInsight' も用意されている。 144 C MAGAZINE 2000 6 こでは , とめ 100 % Java で構築した開発ッ ことで , 正直なところ , 試用する前は速度 や操作性の点で不安があった。同様の懸念 を持たれている方も少なくないであろう。 速度の面では , ネイテイプコードで構築 した開発ツールに比べるとやはり動作が重 い。とくにメニューやツリーを操作したと きのもたっきが気になる。言葉で表現する のは難しいが , あえてたとえるなら , Win dows 98 のスタートメニュー表示がもたっ く感覚に近い。これはおそらく Swing コン ポーネントの動作が重いのであって , JBui Ider3.5 自体の作りに起因するものではない。 むしろ JBuilder 3.5 は , 100%Pure Java アフ リケーションとしては , 複雑な機能を搭載 しているにもかかわらずかなり高速な部類 であろう。 Pentium Ⅱ 400MHz 程度のマシ ンでも , まあまあ実用的な速度ではある。 最新の高速なマシンならばあまりストレス を感じないかもしれない。 ただ , 些細なことかもしれないが , ソー スコードエデイタや各種ツリービューにお いて , スクロールのためにマウスのホイー ルが使えないことがもどかしい。これは 100 % PureJava ゆえの仕方ない制限である。 全体としては , 機能の豊富さと隙のなさ , 完成度の高さに驚いた。無償で利用できる F 。 unda ⅱ。 n 版も数々の魅力的な機能を備え ている。普段は JDK で足りている方々も , JBuilder 3.5 のデザイナやデノヾッガを便利に 感じる局面が必ずあると思われる。ぜひ本 社の付録などを活用して , お試しいただき ロ心、 たいものである。 Borland JBuilder 3.5 < 価格 > Borland JBuilder 3.5 Foundation ( web より登録ダウンロード ) Borland JBuilder 3.5 ProfessionaI 68 , 000 円 BorIand JBuilder 3.5 Enterprise 無料 < 動作環境 > メモリ ードディスク 360 , 000 円 128M バイト以上 150M バイト以上 ・ Windows プラットホーム lntel Pentium Ⅱ / 233MHz 以上 Microsoft Windows 98/NT 4.0 ・ Linux プラットホーム lntel Pentium Ⅱ / 233MHz 以上 IASER 5 Linux 6.0 または日本語 Red Hat Linux 6.1 glibc 2.1.1 以上 , カーネルバージョン 2.2.5 以上 Sun JDK 1.2.2 以降 ・ SO ぬ「 is プラットホーム ULTRASparc 2 以上 Solaris 2.6 または SoIaris 7 ( 2.7 )