タイトルJava Watch on the X》Pure JavaアプリでCocoaを利用カテゴリーCocoa, Java, Java Watch on the X
作成日2002/3/29 14:53:43作成者新居雅行
SwingなどのJava標準のライブラリを使ったアプリケーションなどを作る場合、やはり基本的にはクロスプラットフォームという点を意識してのこととなるだろう。だが、Mac OS向けのアプリケーションで、OSに最適化させるためには、その部分の非互換は目をつむるとしても、OSの機能を利用したくなる。Mac OS Xでは従来のMRJで用意されたクラスもある程度は継続して利用できるようになっているため、その機能を使うのが1つの手段だ。たとえば、Finderで文書ファイルをダブルクリックしたり、あるいは終了のためのAppleEvent対応のハンドラメソッドを定義するということは、Mac向けのアプリケーションでしか機能しないが、やはり必要となる。
ただ、こうした標準のJavaになく、Mac OS X向けの機能を提供するクラスが充実していればいいのだが、MRJのクラスはどちらかといえば、最低限必要なものをなんとか揃えているという感じでもある。OpenDocumentのAppleEventやファイルタイプやクリエイタの処理はなんとかなっても、ある程度以上のこととなると、どうしてもシステムのAPIコールを利用することになる。JDirect 3やあるいはJNIという手段もあるが、少し面倒なプログラミングが必要になる。お手軽な方法はコマンドラインレベルで動くツールを作ってそれを呼び出すという方法もあるが、管理の手間は増える。
一方、Mac OS XのネイティブフレームワークであるCocoaもJavaで利用できる。Cocoaを主体にしたプログラミングでは、Javaの標準ライブラリを利用する場面も多いのであるが、その逆のこともしたいと考えるかもしれない。つまり、SwingなどのJavaの標準ライブラリを主体にしたアプリケーションで、Cocoaのクラスを使いたいという場合である。たとえば、特定のWebページをシステムで設定されている既定のブラウザで開いて表示させるといったような場合である。以前はMRJにopenURLというメソッドがあったのだが、なぜかMac OS Xではサポートされていない。ならば、CocoaのNSWorkspaceのopenURLメソッドを使うのが楽だろう。NSWorkspaceクラスはJavaでも定義されているからだ。だが、単にクラス名をソースに書く以上にいくつかの設定が必要になる。以下の方法は、Project BuilderでSwing Applicationのテンプレートで作成したアプリケーションで、Cocoaのクラスを利用できるようにするために必要な設定をまとめてみた。

まず、JavaのソースにCocoaのクラスを使ったコードを書き込むためには、コンパイル時にCocoaのクラスのインポートが必要なので、ソースの最初に以下のステートメントを記述しておく。

import com.apple.cocoa.foundation.*;
import com.apple.cocoa.application.*;

そして、ソースコードにたとえばボタンをクリックしたイベント処理メソッド内で次のようなコードを書く。これによってブラウザで指定したページを開くが、エラー処理などは割愛させてもらっている。NSWorkspaceについては、クラスの解説ページを参照してもらいたいが、openURLが既定のブラウザで指定したページを開くメソッドだ。

NSWorkspace ws = NSWorkspace.sharedWorkspace();
try {
ws.openURL(new java.net.URL("http://mac-ome.jp/"));
}
catch(Exception ex) { }

そして、アプリケーションのターゲットの設定を開く。「プロジェクト」メニューから「アクティブターゲットの編集」(Command+option+E)を選択する。そして「アプリケーション設定」のタブを選択し、「詳細設定」ボタンをクリックする。ここで、プロパティが一覧されているが、Java→ClassPathの項目を1つ増やして「/System/Library/Java」というパスを、クラスパスに増やしておく。これによって、com.apple.cocoa関連の実際のクラスが参照できるようになるようだ。

なお、Cocoaのフレームワークを利用するように設定しても、実行時にCocoaのクラスを使おうとした段階で、クラスの定義がないと言う実行時エラーになってしまう。/System/Library/Javaを見ればわかるように、ここからパスが切られていて、classファイルそのものが存在している。つまり、Cocoaのclassファイルへの参照については、このパスが組み入れられていないといけないのであるが、各種のJavaのシステムプロパティはどこも参照していない。おそらく、Cocoa-Javaのアプリケーションだと、Javaを呼び出すネイティブのバイナリあたりでこうしたお膳立てはしているのだと思われるが、Swingアプリケーションではそのあたりを自分で設定しないといけない模様だ。だが、コンパイル時には参照をしているのかもしれない。結果的に、Cocoaフレームワークをビルドフェーズに含めなくても、Cocoaの利用はできてしまっている。

なお、Cocoaのクラスは、実際にはその先のObjective-Cのコードを呼び出しているため、メモリ管理は純粋なJavaのクラスと違っている。基本的には、Javaからも同じように利用できるような配慮はされているため、気にしなくてもいいことは多いかもしれない。Javaでは自動的なガベージコレクションを行うなど、メモリ管理をプログラマがほとんど気にしなくてもいいような仕組みが大きな特徴である。一方、Objective-Cはメモリ管理をプログラマが行う必要があるが、Java的な動作もできるし、自分でメモリを確保して解放するということもできる。
いずれにしても、Cocoaのクラスを生成した場合、Javaのメモリ管理下でオブジェクトが生成されるわけではないことをよく理解しておこう。何かの問題が発生したときには糸口になるかもしれないからだ。また、動作がきちんと行われてもコンソールに何らかのメッセージが出てくることある。また、スレッド関連の処理をする場合には、NSAutoreleasePoolの解説も参照してもらいたい。このクラスは、Objective-Cではメモリ領域の管理クラスだが、Javaでは独特の使い方をする。Cocoa-Javaでプログラミングをする人は、JavaとObjective-Cのつながりをどうやっているかという文書はやはり目を通しておく必要があるだろう。CocoaのProgramming Topicの中に、「Java/Objective-C Language Integration」という項目があるので、それを参考にしてもらいたい。

∽∽∽∽∽∽∽この項、以上∽∽∽∽∽∽∽[新居雅行]∽∽∽∽∽∽∽
関連リンク