J2ME CLDC/KVM Palmチュートリアル
- Release 1.0対応、2000年5月30日版 -

     
J2ME CLDC/KVM Palmとは?

J2ME CLDC

Java 2プラットフォームの仕様には、サーバ環境向けのEnterprise Edition(J2EE)、デスクトップ環境向けのStandard Edition(J2SE)、そして組み込み機器向けのMicro Edition(J2ME)の3つの仕様グループがあります。J2MEについてはさらに、ネットワーク情報機器用のConnected Device Configuration(CDC)と、CPU能力やメモリ容量が制限された携帯型ネットワーク情報機器用のConnected, Limited Device Configuration(CLDC)の2つの基本ライブラリ構成が、標準化活動(Java Community Process)によって策定されつつあります。PalmプラットフォームのJavaは、このJ2ME CLDC仕様に準拠した最初のJavaということになります。

MIDP

J2ME CLDC仕様に準拠したJava対応製品としては、携帯電話やページャ、携帯情報端末(PDA)などが各社によって計画されています。CLDC仕様は、さまざまな製品ジャンルに共通する基本ライブラリ仕様を定義したものであり、ユーザインタフェースなどの詳細な仕様は、Mobile Information Device Profile(MIDP)などのプロファイルの中で規定されることになっています。すなわち組み込み機器のJava仕様は、Edition、Configuration、Profileの3つのレイヤからなる仕様の組み合わせによってはじめて完全に定まることになります。

KVM

KVM(K Virtual Machine)は、J2ME CLDC仕様との組み合わせで使用することが想定されている新しいJavaの実行環境(Java仮想マシン)で、Kバイトオーダー(64K〜128K程度)のメモリで動作することからそのように呼ばれています。現時点では、Palm、Solaris、Windowsの3つのプラットフォームについて、Sun Community Sourceサイトからリファレンス実装とソフトウェア開発キットを入手することができます。

KJava

JavaOne '99では、KVMのプロトタイプ実装であるKJavaがプリインストールされたPalm Vが参加者に低価格で提供されて話題になりました。KJavaはJavaOneでのデモストレーション用に用意されたバージョンにすぎないため、J2ME CLDC仕様とは大きく異なっている部分もあり、また実装の完成度も決して高いものではありませんでした。

Spotless

KVMのプロトタイプ実装としては、この他にSpotlessと呼ばれるシステムがSun Labsによって公開されています。SpotlessはKJava開発のベースになったシステムです。このため両者は多くの共通点をもっていますが、動作アプリケーションや開発ツールには残念ながら互換性がありません。

J2ME CLDC/KVM Palm

このチュートリアルでは、Palmプラットフォームで動作するJ2ME CLDC/KVM対応アプリケーション(以下、単にCLDCアプリケーションと称する)を作成する手順を説明します。説明とサンプルプログラムは、2000年5月24日に配付開始された正式リリース版(Release 1.0)に対応しています。以前のバージョンに対応した説明については、過去のチュートリアル(EA 0.1対応版EA 0.2対応版Beta 2対応版Beta 3対応版)をご参照ください。

開発キットをセットアップする

ライセンス

J2ME CLDC/KVMの正式リリース版は、Sun Community Source License(SCSL)と呼ばれるライセンス規約に従ってソースコート付きのパッケージとして配付されています。SCSLはオープンソースライセンスの一種ですが、知的所有権や守秘義務に関して大きな制約を課した内容になっています。開発キットをダウンロードする際には、SCSLライセンスの主旨と概要について理解し、同意できるかどうかをあらかじめ十分に検討しておくことをお勧めします。

ダウンロード

CLDCのソフトウェア開発キットは、Sun Community Sourceサイトからダウンロードできます。

J2ME CLDC/KVM Release 1.0

Palmプラットフォームでの開発をおこなうためには、Windows版とSolaris版を含む基本パッケージとPalm版の追加パッケージの両方をダウンロードする必要があります。それぞれj2me_cldc-1_0-src-winsol.zip(4,800,591バイト)とj2me_cldc-1_0-src-palm_overlay.zip(520,634バイト)というアーカイブファイルにまとめられています。

セットアップ

はじめに基本パッケージを展開し、続いてPalm版の追加パッケージを同一の場所に展開することによって上書きマージされるようにします。これによりCLDCアプリケーションに必要なファイルがすべてひとつのフォルダにまとめられます。

両方のパッケージを展開してマージすると、CLDCの開発キットはapibinbuilddocs、jamkvmsamplestoolsの計8つのフォルダから構成されていることがわかります。これらを含むフォルダ(以降は、CLDCフォルダと呼ぶ)を適当な場所に移動すれば、開発キットのセットアップは完了です。

HotSyncでプログラムをインストールする

ファイル構成

Palmマシンにインストールするファイルは、binフォルダにまとめられています。この中のKVM.prcがJava実行環境とクラスライブラリ、KVMutil.prcがオプション設定ユーティリティで、この2つのファイルは必ずインストールしなければなりません。

kvm.exekvm_j.exepreverify.exeはWindowsで動作する開発用ツール(kvmkvm_jpreverifyはSolaris用)ですから、Palmマシンにはインストールしません。.prcの拡張子をもつ他のファイルは、すべてデモアプリケーションです。

HotSync

Palm Desktop(Mac OSの場合はHotSync Manager)を起動して、アプリケーションのインストールリストにKVM.prcファイルとKVMutil.prcファイルを追加します。サイズも大きくないので、とりあえずデモアプリケーションもすべてインストールしておくとよいでしょう。

ファイルの追加が完了したら、HotSyncを実行します。これでCLDCのJava実行環境の準備が整いました。

デモアプリケーションを動かしてみる

KVMアイコン

KVMとデモアプリケーションをインストールすると、右図のようなアイコンが表示されます。JavaのマスコットであるDukeのアイコンがついているのが、CLDCのJava実行環境とユーティリティです。

KVMのアイコンをタップするとはじめにライセンス条項が表示され、「Accept」ボタンをタップするとKVMutilのオプション設定画面が表示されます。ここでは最大ヒープメモリサイズを指定したり、実際に割り当てられたヒープメモリサイズをアプリケーションの起動時に表示するように設定したりすることができます。なお、このオプション設定の画面は、KVMのアイコンとKVMutilアイコンのどちらをタップした場合にも表示されます。

デモアプリケーション

デモアプリケーションは、それぞれのアイコンをタップすることによって起動します。起動するとDukeの画像が表示され、初期化のために数秒間待たされます。

右図は、フラクタル図形を表示するデモアプリケーション、Dragonを実行しているところです。

クラスライブラリを準備する

toolsフォルダ

プログラムの作成をはじめる前に、アプリケーションの開発に必要なクラスライブラリを準備しておきましょう。toolsフォルダにはクラスファイルをPRC形式に変換するMakePalmAppクラスをはじめとする開発用のツールが格納されています。ところがこれらはソースコードでしか提供されていないため、利用する前に自分でコンパイルしておく必要があります。以下のようにコマンドラインを入力すると、binフォルダ内のtoolsフォルダにクラスファイルが作成されるとともに、必要なリソースがコピーされます。

> mkdir C:\cldc\bin\tools
> mkdir C:\cldc\bin\tools\classes
> javac -d C:\cldc\bin\tools\classes -classpath C:\cldc\bin\tools\classes
  C:\cldc\tools\palm\src\palm\database\*.java
> copy C:\j2me_cldc\tools\palm\src\palm\database\DefaultTiny.bmp
  C:\j2me_cldc\bin\tools\classes\palm\database
> copy C:\j2me_cldc\tools\palm\src\palm\database\Wrapper.prc
  C:\j2me_cldc\bin\tools\classes\palm\database

クラスパス

binフォルダの内部には、ここで作成したtoolsフォルダ以外にも、CLDCクラスライブラリが格納されているapiフォルダとサンプルプログラムに必要なクラスが格納されたsamplesフォルダがあります。これらはこのままの状態でもかまわないのですが、すべてのクラスをひとつの場所にまとめておくと、クラスパスを指定する際などに便利です。

ここではCLDCフォルダにlibフォルダを新規に作成し、その中にapiフォルダのclassesフォルダ、toolsフォルダのclassesフォルダ、samplesフォルダのclassesフォルダのすべてのファイルをコピーしたclassesフォルダを作ることにして、以下の説明ではこのclassesフォルダをクラスパスに指定することにします。

さらに、classesフォルダをZIP形式にアーカイブ化したclasses.zipファイルを作成しておけば、クラスライブラリの扱いはより便利になります(Mac OSの場合は長いクラス名が使用できないという制限があるため、ZIP形式にアーカイブファイルを利用しなければなりません)。

Hello Worldプログラムを作成する

Spotletクラス

プログラムのソースファイルは任意の場所に作成すれば良いのですが、ここではCLDCフォルダにprojectsフォルダを新規に作成し、その中に以下の内容のHelloWorld.javaファイルを作成することにします。CLDCアプリケーションは、この例のようにSpotletクラスをサブクラス化することにより定義します。

import com.sun.kjava.*;

public class HelloWorld extends Spotlet {
    Graphics g = Graphics.getGraphics();

    public static void main(String[] args) {
        (new HelloWorld()).register(NO_EVENT_OPTIONS);
    }

    public HelloWorld() {
        g.clearScreen();
        g.drawString("Hello, world!", 50, 50, g.PLAIN);
    }

    public void penDown(int x, int y) {
        System.exit(0);
    }
}

コンパイル

作成したソースファイルをコンパイルするには、作業ディレクトリをprojectsフォルダに移動して、以下のようにjavaコマンドのコマンドラインを入力します(ここではCドライブにCLDCフォルダをセットアップしたと仮定しています)。

> cd \cldc\projects
> mkdir tmp
> javac -g:none -d tmp -classpath tmp;C:\cldc\lib\classes
  -bootclasspath C:\cldc\lib\classes HelloWorld.java

Mac OSの場合は、javacアプリケーションにHelloWorld.javaファイルをドラッグ&ドロップします。そしてjavacの設定フィールドに以下のように入力し、「Do Javac」ボタンをクリックします(ここではMac OSボリュームにCLDCフォルダをセットアップしたと仮定しています)。

Source files:       /Mac OS/CLDC/projects/HelloWorld.java
Destination folder: /Mac OS/CLDC/projects/tmp
Classpath:          /Mac OS/CLDC/projects/tmp
                    /Mac OS/CLDC/lib/classes.zip

検証とテスト

次に作成したクラスファイルを検証します。デスクトップ環境のJavaでは、Java仮想マシンによって実行時に検証がおこなわれますが、J2ME CLDC環境では、実行時の負担を軽くするために検証プロセスは2段階に分けておこなわれます。すなわち、preverifyツールによって事前に生成したスタックマップ情報をクラスファイルに追加することによって、少ないメモリ容量でも実行時の検証ができるようにしています。

クラスファイルを事前検証するには、以下のようにpreverifyコマンドのコマンドラインを入力します。これによってtmpフォルダ内のクラスファイルが検証され、検証済のクラスファイルがclassesフォルダに作成されます。

> mkdir classes
> C:\cldc\bin\preverify -d classes -classpath C:\cldc\lib\classes tmp

こうして作成したクラスファイルは、kvmコマンドを利用してテスト実行することができます。kvmコマンドは、後述するPalm OS Emulatorのような本格的なエミュレータではありませんが、簡易的な動作確認には非常に便利です。

> C:\cldc\bin\kvm -classpath classes;C:\cldc\lib\classes HelloWorld

Mac OSの場合は、現時点ではコマンドツールが提供されていないため、検証とテストをおこなうことはできません。

コンバージョン

クラスファイルをPalmマシンで扱えるようにするためには、最終的にはPRC形式に変換する必要があります。このコンバージョンをおこなうためのMakePalmAppクラスは、classesフォルダのpalm.databaseパッケージに格納されています。以下のようにjavaコマンドのコマンドラインを入力すると、HelloWorld.classファイルからHelloWorld.prcファイルを生成することができます。javaコマンドとMakePalmAppクラスの両方に必要なために、classpathオプションが2回指定されていることにご注意ください。

> java -classpath C:\cldc\lib\classes palm.database.MakePalmApp
  -bootclasspath C:\cldc\lib\classes -classpath classes HelloWorld

Mac OSの場合は、JBinderyアプリケーションにHelloWorld.classファイルをドラッグ&ドロップします。そしてJBinderyの設定フィールドに以下のように入力し、「Run」ボタンをクリックしてください。

Command Panel
    Class name:          palm.database.MakePalmApp
    Optional parameters: -bootclasspath /Mac OS/CLDC/lib/classes.zip
                         -classpath classes HelloWorld
Classpath Panel
    Addtions to class path: $CLASSPATH
                            /Mac OS/CLDC/lib/classes.zip

projectフォルダに生成されたHelloWorld.prcファイルをHotSyncでPalmマシンにインストールすれば、他のデモアプリケーションと同様にHelloWorldプログラムを実行することができます。

スクリーンの任意の場所をタップするとHelloWorldプログラムは終了します。

アプリケーションプログラムの作成方法とオプションの詳細については、docsフォルダ内のtools.htmlファイルにまとめられていますので、一度目を通しておくとよいでしょう。

Palm OSエミュレータを利用する

POSE

CLDCで動作するアプリケーションを開発するときに、作成中のプログラムをその都度Palmマシンにインストールして動作テストをしていたら大変手間がかかります。そこで、Palmの開発ツールのひとつであるPalm OS Emulator(POSE)を利用することをお勧めします。

ダウンロード

POSEは、3Com/Palm Computingの開発者サイトからダウンロードすることができます。POSEにはWindows用(4,889,680バイト)とMac OS用(5,169,641バイト)があり、どちらも最新版はバージョン3.0a4となっています。

Palm OS Emulator Version 3.0a4

インストール

ダウンロードしたファイルを展開すると、エミュレータプログラムのEmulator.exe(Mac OSの場合はPalm OS Emulator)やドキュメントフォルダなどから構成されるフォルダが得られます。このフォルダを適当な場所に移動すれば、インストールはほぼ完了です。

ROMイメージの作成

最後に自分が使用しているPalmマシンのROMイメージファイルを作成します。ROMイメージファイルのは、POSEに付属のROM Transfer.prcファイルをPalmマシンにインストールしてからPOSEを起動し、「File」メニューの「Transfer ROM」コマンドを実行して指示に従うだけで簡単に作成することができます。

日本語を表示する

日本語文字列

CLDCでは、日本語の文字列をそのままdrawString()メソッドに与えても正しく表示することができません。これはCLDCがUnicodeの文字列処理を完全にサポートしていないためです。ところが以下の例のように、Shift JISの漢字コードをcharの2文字に分割したものを使うと日本語を表示することができます。

import com.sun.kjava.*;

public class HelloJapan extends Spotlet {
    Graphics g = Graphics.getGraphics();

    public static void main(String[] args) {
        (new HelloJapan()).register(NO_EVENT_OPTIONS);
    }

    public HelloJapan() {
        String message = "\u0082\u00cd\u0082\u00b6\u0082\u00df\u0082\u00c4"
            + "\u0082\u00cc\u0093\u00fa\u0096\u007b\u008c\u00ea";
        g.clearScreen();
        g.drawString(message, 50, 50, g.PLAIN);
    }

    public void penDown(int x, int y) {
        System.exit(0);
    }
}            

コンパイルから実行まで

プログラムのコンパイルから実行までの手順は、HelloWorldプログラムの場合と同じで、以下のようにjavaコマンドのコマンドラインを入力するとHelloJapan.prcファイルを作成することができます。

> cd \cldc\projects
> javac -g:none -d tmp -classpath tmp;C:\cldc\lib\classes
  -bootclasspath C:\cldc\lib\classes HelloJapan.java
> C:\cldc\bin\preverify -d classes -classpath C:\cldc\lib\classes tmp
> java -classpath C:\cldc\lib\classes palm.database.MakePalmApp
  -bootclasspath C:\cldc\lib\classes -classpath classes HelloJapan

Mac OSの場合も、HelloWorldと同一の手順でコンパイルとコンバージョンをおこないます。

コンバージョンが完了したら、POSEにインストールして動作を確認してみることにしましょう。POSEを起動して「File」メニューの「Install Application/Database」コマンドを実行し、作成したHelloJapan.prcファイルを選択します。これでCLDCアプリケーションがPOSEにインストールされていますので、実行してみてください。

スクリーンの任意の場所をタップするとHelloJapanプログラムは終了します。

イメージを表示する

Bitmapクラス

CLDCには、イメージを扱うためのクラスとしてBitmapクラスが用意されています。ところがBitmapクラスのインスタンスは、GIF形式やJPEG形式のイメージファイルから生成することができないので、ビットマップデータのバイト列を直接与えることによって生成しなければなりません。

classesフォルダのpalm.databaseパッケージに格納されているBitmapクラスは、Windowsビットマップファイル(BMP形式ファイル)からこのビットマップデータのバイト列を出力するためのツールです。例えば、DukeIcon.bmpファイルからdukeBitmapという名前の変数としてDukeIcon.txtファイルにビットマップデータを生成するには、以下のようにjavaコマンドのコマンドラインを入力します。

> java -classpath C:\cldc\lib\classes palm.database.Bitmap
  DukeIcon.bmp -dump dukeBitmap DukeIcon.txt

Mac OSの場合は、JBinderyの設定フィールドに以下のように入力して、「Run」ボタンをクリックしてください。

Command Panel
    Class name:          palm.database.Bitmap
    Optional parameters: DukeIcon.bmp -dump dukeBitmap DukeIcon.txt
Classpath Panel
    Addtions to class path: $CLASSPATH
                            /Mac OS/CLDC/lib/classes.zip

イメージの描画

以下は、KVMのアイコンでもあるDukeのイメージ(24 X 24ピクセル)から出力したビットマップデータ(ボールドで表示された部分)を使った簡単なプログラム例です。

import com.sun.kjava.*;

public class DukeImage extends Spotlet {
    Graphics g = Graphics.getGraphics();
    Bitmap dukeBitmap = new Bitmap((short)4, new byte[] {
        // File DukeIcon.bmp;  size: 24x24
           0,    0,    0,    0,   24,    0,   24,    0,
          14,    0,   56,    0,   15,    3,   48,    0,
           7, -125,   -2,    0,    7,  -63,   -2,    0,
           7,  -32,  -16,    0,    7,  -15,   -8,    0,
           6,  -79, -104,    0,    5,   90,    0,    0,
           6,  -90,    0,    0,   13,  -58,    0,    0,
          56,    2,    0,    0,   72,    2,    0,    0,
          40,    1,    0,    0,   16,    1,    0,    0,
          48,    1,  122,    0,   48,    0,  -82,    0,
          48,    0,  -86,    0,  112,  -32, -128,    0,
          35,   16,  -86,    0,   36,   89,   84,    0,
          26,  -82,  -86,    0,    0,    0,    0,    0
    });

    public static void main(String[] args) {
        (new DukeImage()).register(NO_EVENT_OPTIONS);
    }

    public DukeImage() {
        g.clearScreen();
        g.drawBitmap(68, 68, dukeBitmap);
    }

    public void penDown(int x, int y) {
        System.exit(0);
    }
}

生成したイメージを表示するには、GraphicsクラスのdrawBitmap()メソッドを使用し、描画始点の座標とBitmapオブジェクトを指定して描画をおこないます。

プログラムのコンパイルから実行までの手順は、これまでの例題とほとんど同じなので、これ以降の説明では省略することにします。

Dukeのアイコンが表示できることを確認したら、スクリーンの任意の場所をタップしてプログラムを終了します。

データの入出力

Databaseクラス

Palm OSにおけるデータの入出力は、ファイルシステムではなく簡単なデータベースの機能を使って実現されています。CLDCからデータベースの機能を利用するには、Databaseクラスを使います。

Databaseクラスを利用してデータを出力するには、はじめにcreate()クラスメソッドによってテータベースを作成します。このときに、英字4文字からなるタイプとクリエータを整数値で指定する必要があります。一方、データベースからデータを入力するときには、このタイプとクリエータを指定することによって、特定のアプリケーションの特定のデータにアクセスすることができます。例えば、タイプとして"DATA"、クリエータとして"memo"を指定してDatabaseクラスのインスタンスを生成すると、メモ帳のデータをオープンすることができます。

int dbType = 0x44415441;    // "DATA"
int dbCreator = 0x6d656d6f; // "memo"
Database db = new Database(dbType, dbCreator, Database.READONLY);

電話帳プログラム

以下のプログラム例は、Databaseクラスを使って作った簡単な電話帳プログラムです。

import com.sun.kjava.*;

public class PhoneBook extends Spotlet {
    Database db;
    Graphics g = Graphics.getGraphics();
    TextBox textBox;
    TextField textField;
    Button addButton, clearButton, quitButton;

    public static void main(String[] args) {
        (new PhoneBook()).register(NO_EVENT_OPTIONS);
    }

    public PhoneBook() {
        int dbType = 0x44415441;    // "DATA"
        int dbCreator = 0x70686f6e; // "phon"
        db = new Database(dbType, dbCreator, Database.READWRITE);
        if (!db.isOpen()) {
            Database.create(0, "PhoneDB", dbCreator, dbType, false);
            db = new Database(dbType, dbCreator, Database.READWRITE);
        }
        textBox = new TextBox("", 8, 8, 144, 106);
        textField = new TextField("Phone", 5, 122, 150, 10);
        addButton = new Button("Add", 135, 142);
        clearButton = new Button("Clear", 105, 142);
        quitButton = new Button("Quit", 78, 142);
        paint();
    }

    public void paint() {
        g.clearScreen();
        g.drawBorder(5, 5, 150, 112, g.PLAIN, g.SIMPLE);
        StringBuffer buffer = new StringBuffer();
        int records = db.getNumberOfRecords();
        for (int i = 0; i < records; i++)
            buffer.append(new String(db.getRecord(i))).append('\n');
        textBox.setText(buffer.toString());
        textBox.paint();
        textField.paint();
        addButton.paint();
        clearButton.paint();
        quitButton.paint();
        textField.setFocus();
    }
    
    public void keyDown(int keyCode) {
        textField.handleKeyDown(keyCode);
    }
    
    public void penDown(int x, int y) {
        if (addButton.pressed(x, y)) {
            String text = textField.getText();
            if (text.length() > 0) {
                textField.loseFocus();
                db.addRecord(text.getBytes());
                textField.setText("");
                paint();
            }
        } else if (clearButton.pressed(x, y)) {
            textField.loseFocus();
            int records = db.getNumberOfRecords();
            while (records-- > 0)
                db.deleteRecord(records);
            paint();
        } else if (quitButton.pressed(x, y)) {
            db.close();
            System.exit(0);
        }
    }
}

このプログラム実行すると、最初に"PhoneDB"という名前のデータベースが作成され、プログラム終了後もそこに入力した電話番号のデータが保存されます。

電話番号を登録するには、 テキストフィールドに情報を入力して「Add」ボタンをタップします。また、「Clear」ボタンをタップすると、これまでに登録した電話番号がすべて削除されます。

プログラムを終了するときは、「Quit」ボタンをタップしてください。

© 1999, 2000 Jun Fujisawa. All rights reserved.

[Home | Mailing List | Tutorial]