一、J2ME概述
到目前為止,大部分人都已非常熟悉 Java 2平臺,以及 Sun如何把 Java技術(shù)分成三個版本 (標(biāo)準版、袖珍版以及企業(yè)版),Sun 在1999年6月時推出了 Java 2袖珍版 (J2ME)來滿足消費電子和嵌入設(shè)備的需要。J2ME是為了那些使用有限的能源、有限的網(wǎng)絡(luò)連接 (常常是無線連接)以及有限圖形用戶界面能力的設(shè)備開發(fā)的。它初的目標(biāo)是 16位或 32位處理器,16 MHz時鐘頻率, 512K或更少內(nèi)存的設(shè)備。乍一看之下, J2ME就像一個沒有綁定明顯主題的松散的應(yīng)用程序接口和技術(shù)規(guī)范。我們想通過說它不是什么東西的方法來描述它,它不是一組用于臺式機 Java應(yīng)用程序規(guī)范,如果你再觀察仔細一些,你會發(fā)現(xiàn)所有的 J2ME組件都圍繞一個中心,這些中心被稱為configuration(配置 ,Sun的市場營銷資料也稱它們 design centers,設(shè)計中心),它們中間的每一個都是用于消費電子和嵌入設(shè)備的特別的類。
Connected limited device configuration(有限連接設(shè)備配置,簡稱 CLDC ) 這個配置定義了 Java應(yīng)用程序接口以及支持手持設(shè)備的技術(shù),就像 Sun的文檔中所描述的那樣, " devices that you hold in your hand(你握在手中的設(shè)備) " Palm序列手持設(shè)備可能是這一領(lǐng)域的設(shè)備的的例子,特別是它有開發(fā) CLDC的功能以及 Palm設(shè)備運行期系統(tǒng)可用。
Connected device configuration(連接設(shè)備配置 CDC ) 這個配置定義支持象 Sun文檔中所說, " devices that you plug into plug into the wall(你插入墻的設(shè)備)的設(shè)備的應(yīng)用程序接口和技術(shù),這樣的設(shè)備的一個例子可能就是機頂盒。
這兩種配置不同的地方就在于它們應(yīng)用于的裝置的能力, CLDC設(shè)備的處理器能力有限 (與臺式機系統(tǒng)比較 ),并且存儲器大小一般也只在128 KB到 512 KB之間, 與此同時,CDC系統(tǒng)就不同了,它可能有 32位或 64位處理器,以及有限的存儲容量,不過它的下限也得超過512K。 它遵循的原則就是,每個不同的能力硬件的配置都將被不同的虛擬機支持。 基于 CDC的系統(tǒng)使用一個功能強勁的虛擬機,而基于 CLDC系統(tǒng)的使用 KVM 。
每個配置代表一種低水平的,基本的應(yīng)用程序接口,在這兩個相似基礎(chǔ)之上是 profile(簡表),用于特殊設(shè)備的額外的應(yīng)用程序接口。 我想通過看一張來自SUN提供的文檔中的圖表 (參見圖 1 )來解釋這其中的關(guān)系。
J2ME的體系結(jié)構(gòu)被橫向地分成三層,縱向分成兩部分。配置包括一個控制配置核心類的虛擬機, 具體的簡表位于每個配置之上。
J2ME現(xiàn)在定義兩個配置, Connected Device configuration(連接設(shè)備配置 CDC )和限制性更強的 Connected Limited Device Configuration (有限連接設(shè)備配置)。 簡表的實現(xiàn)是 Java應(yīng)用程序接口的一個集合,用于適應(yīng)被定義配置的應(yīng)用程序接口提供的服務(wù),簡表是一個完整的運行環(huán)境,一個在簡表上執(zhí)行的應(yīng)用程序不需要額外的支持類。
J2ME沒有定義滿足這兩種配置的標(biāo)準化用戶接口,Sun也承認現(xiàn)在的消費設(shè)備多種多樣,用戶界面也各不一樣,所以定義一個可用于所有用戶的界面是一場失敗的戰(zhàn)爭。 J2ME中的用戶界面定義在簡表中。
二、J2ME的體系結(jié)構(gòu)
現(xiàn)在個人計算機系統(tǒng)的數(shù)量和種類已經(jīng)發(fā)展到無法控制的地步,請你想一想,你編寫的程序運行在“信息家電”舞臺的情景吧,這些信息家電包括呼叫器,行動電話,像Palm這樣的個人數(shù)字助手(PDA),電視機頂盒,POS終端以及其他的消費電子設(shè)備。現(xiàn)在全世界上光是手提電話生產(chǎn)商就有許多,更不用說別的家電設(shè)備了,而且每一種家電設(shè)備又有不同的特性和界面。所以,你可以想到, Java應(yīng)用程序的輕便性以及能夠解決開發(fā)這么許多不同的設(shè)備程序的能力,使大家對J2ME有很大的期許。當(dāng)然,為了更好的開發(fā)這些信息家電,就要求把Java的精髓壓縮進一個非常小的程序包中,這就是J2ME。
J2ME是一種通過許多部件和規(guī)范的技術(shù), 這眾多的部件和規(guī)范幫助 J2ME來滿足這眾多的消費產(chǎn)品的不同的需要。和所有的爪哇程式語言技術(shù)一樣,在它的核心屬于一種虛擬機。 就像使用所有 Java技術(shù)一樣,J2ME的核心也在一種虛擬機中。 初,用于 J2ME應(yīng)用程序虛擬機的被稱作 Kilobyte virtual machine或簡稱 KVM。就像它名稱的含義, KVM比較小,通常只有 128K或更少。這比起我們通常了解和使用的 Java 2標(biāo)準版 Java虛擬機 ( JVM )的 32 MB來說就小得多了。
用于連接虛擬機的是一系列配置和簡表,它們提供了用于特定 J2ME環(huán)境的類應(yīng)用程序接口(見圖二)。 每個配置和簡表處理一般或具體的消費產(chǎn)品,配置和簡表規(guī)范是由多種多樣的設(shè)備生產(chǎn)商和用戶共同開發(fā)并建立的。配置是用于一組通用設(shè)備的小的 Java平臺, 常常歸為一種橫向的設(shè)備分組,相對來說,橫向分組設(shè)備是那些共享相同的內(nèi)存安排,通信帶寬,能量需求以及用戶能力的設(shè)備,一般認為配置能夠提供這眾多的設(shè)備的所有需求。
Java虛擬機是 J2ME技術(shù)的核心,但是配置和簡表提供特殊環(huán)境的類應(yīng)用程序接口。配置是用于一組通用設(shè)備的小的 Java平臺,而簡表則為具體的設(shè)備家族或特別的應(yīng)用程序提供更具體的能力。
J2ME領(lǐng)域的新的開發(fā)者常常被這些事實困惑的, 事實上, Sun的個配置(現(xiàn)在只是一種配置的引用實現(xiàn) )帶有稱為 KVM的虛擬機引用實現(xiàn), KVM滿足配置的虛擬機的必要條件。然而, Sun的 KVM也可以被另外一個虛擬機所代替,現(xiàn)在, 正是因為配置和虛擬機結(jié)合得有點緊密,因此導(dǎo)致了這么多的混亂。
另一方面,簡表完善了 配置,為某個具體的設(shè)備家族或某個具體的工業(yè)片段應(yīng)用程序提供更高的性能。 換言之, 簡表為具體的縱向市場的設(shè)備比如說行動電話提供更多的性能。這里的關(guān)鍵就是 簡表必須完善 配置, 沒有 配置和虛擬機提供核心類應(yīng)用程序接口和運行期環(huán)境的話,簡表也不會工作。
通常,簡表為一種給定的垂直分組設(shè)備提供用戶界面、輸入法、持久性機制。這類 簡表被認為是發(fā)展這些設(shè)備應(yīng)用程序的完整的工具包。我們見到多的應(yīng)用程序簡表的例子就移動電話簡表和個人數(shù)字助手(PDA)簡表,其他簡表為范圍寬廣的設(shè)備提供非常特殊的功能或應(yīng)用程序可移植性,這方面的例子就是提供遠程方法調(diào)用 ( RMI )功能的簡表和提供統(tǒng)一銀行事務(wù)的簡表。
虛擬機、 配置、 簡表…你是不是已經(jīng)被搞迷糊了? 如果這樣的話,我們就來簡化一下 J2ME體系結(jié)構(gòu)吧。 如果你想為小型信息家電編寫 Java應(yīng)用程序的話,你就需要兩個前提:一個 配置和至少一個 簡表。 現(xiàn)在, 一般是配置捆綁了虛擬機和一套針對你的平臺所能夠用的橫向分組設(shè)備的Java類庫。其次,你至少還需要一個 簡表來為你的平臺提供附加的 Java類,這個 簡表通常會為你的設(shè)備提供用戶界面、輸入和數(shù)據(jù)庫類。有了這兩個前提,你就了使用 Java為你的設(shè)備編寫應(yīng)用程序的基本的J2ME環(huán)境。
三、詳細談?wù)凧2ME配置
J2ME可以在好幾個不同的配置中進行配置。就像先前提到的,每個配置為一組通用設(shè)備提供小的 Java平臺,到目前為止,只有兩種配置規(guī)范。通過 Java規(guī)范定義的這兩種配置是 Connected Limited Device Configuration (有限連接設(shè)備配置, CLDC )和 Connected Device Configuration (連接設(shè)備配置 CDC )。
CLDC是為使用較小的存儲容量的設(shè)備設(shè)計的 (參見圖3 )。 CLDC用于內(nèi)存在128到 512K之間的消費電子設(shè)備, 這一類別中典型代表的設(shè)備包含呼叫器、行動電話、PDA和POS終端;而另一方面, CDC用于比 PC機小但是具有比 512K內(nèi)存多的設(shè)備,這一類設(shè)備包括互聯(lián)網(wǎng)絡(luò)電視系統(tǒng)、機頂盒、POS系統(tǒng)、汽車導(dǎo)航以及娛樂系統(tǒng)。一般來說, CDC使小型設(shè)備只要具有少量的資源,至少比臺式機要少的資源就能進行Java編程,而CLDC使小型設(shè)備所擁有的資源只要比一張智能卡多一點就可以進行Java編程了。
J2ME有兩個配置CLDC和 CDC,CLDC是為使用較小的存儲容量的設(shè)備設(shè)計的,而CDC用于比 PC機小但是具有比 512K內(nèi)存多的設(shè)備。
除了在容量大小和能力上對虛擬機規(guī)定了必要條件,配置還規(guī)定了類應(yīng)用程序接口要包含常見的 java.io、 java.net、 java.util和 java.lang包,配置可能還要包括其他需要的程序包。
CLDC
CLDC起源可以追溯到1999年JavaOne大會上介紹的Sun的個袖珍版 Java和個 KVM以及相關(guān)的類庫,雖然 CLDC和所有的配置都滿足成為虛擬機的條件,可它本身還不是虛擬機,CLDC的引用實現(xiàn)只是包含在當(dāng)前的分布中的 KVM。
根據(jù)規(guī)范中所說,運行 CLDC的設(shè)備應(yīng)該有 512K或更少的內(nèi)存空間、一個有限的電源供給 (通常是使用電池)、有限的或斷斷續(xù)續(xù)的網(wǎng)絡(luò)連接性 ( 9600 bps或更少 )以及多樣化的用戶界面甚至沒有用戶界面。 通常說來,這個配置是為個人化的、移動的、有限連接信息設(shè)備而設(shè)計,比如呼叫器、移動電話和 PDA等。
與 J2SE相比, CLDC缺少下列所說的這些特征:
AWT(抽象窗口開發(fā)包), Swing或其他圖形庫
用戶定義類裝載器
類實例的終化
弱的引用
RMI
Reflection(映射)
CLDC有四個包: java.lang、 java.util、 java.io和 javax.microedition。 除了 microedition包以外,其他的這幾個包都是J2SE包的核心子集,CLDC采用這些J2SE類庫,但是把其中一些在微型設(shè)備中用不到類、屬性、方法去掉了。因此 CLDC類庫有許多細微的差別。 如果您想研究J2SE和 CLDC類庫之間的差別,請參閱相關(guān)文檔,在此就不詳細說明了。
想要理解為什么CLDC去除這么多J2SE中重要的類和特征,請回想一下與 CLDC相關(guān)的兩條基本原理。首先,它只有 512K的內(nèi)存空間, 而像RMI和映射需要的內(nèi)存太大了。 其次,配置必須滿足為一組通用設(shè)備提供小的 Java平臺。 在個人移動信息設(shè)備領(lǐng)域中,許多系統(tǒng)都不能支持 J2SE中的眾多的特征。 例如,許多消費電子產(chǎn)品不能支持浮點數(shù); 因此 Float(浮點類)和 Double(雙精度類)就被刪除了。 再看另外一個例子,許多系統(tǒng)沒有或不提供訪問一個文件系統(tǒng)的功能或權(quán)限。 因此與文件有關(guān)的類也被丟棄了。又如,錯誤處理是一個代價非常高的過程處理,在許多消費電子設(shè)備中,故障恢復(fù)是很難的甚至是不可能的。 所以在 CLDC中,許多錯誤處理類也被刪除了。
java.microedition程序包提供了一個一般的結(jié)構(gòu)來替代許多 J2SE網(wǎng)絡(luò)輸入/輸出類。 CLDC一般連接器結(jié)構(gòu)還定義了一個 Connector類,允許許多不同類型的連接能夠使用靜態(tài)方法,下表列出使用同一個Connector類創(chuàng)建和打開五種不同類型的連接的方法:
HTTP Connector.open("http://www.xyz.com");
套接字 Connector.open("socket://111.222.111.222:9000");
通訊端口 Connector.open("comm:1;baudrate=9600");
數(shù)據(jù)報 Connector.open("datagram://111.222.111.222");
文件 Connector.open("file:/xyz.dat");
一般連接器結(jié)構(gòu)提供給應(yīng)用程序開發(fā)者一個到通用低水平硬件的簡單的映射表。成功執(zhí)行 open語句將返回一個實現(xiàn)一般連接界面的對象。
CDC
CDC涵蓋了個人電腦與有至少 512K內(nèi)存的小型設(shè)備之間的中間地帶。現(xiàn)在,這一類設(shè)備通常是共享的、固定的 (不用移動)網(wǎng)絡(luò)連接信息設(shè)備,像電視機機頂盒,網(wǎng)絡(luò)電視系統(tǒng)、互聯(lián)網(wǎng)電話與汽車導(dǎo)航/娛樂系統(tǒng)等等。
首先,CDC基于 J2SE 1.3應(yīng)用程序接口,包含所有定義在CLDC規(guī)范(包括 javax.microedition程序包)中的Java語言應(yīng)用程序接口。與CLDC相比, CLDC所有缺少的特性和類在 CDC中都被補齊,包含映射、終化、所有的錯誤處理類、浮點數(shù)、屬性、輸入/輸出 ( File、 FileInputStream等等 )和弱的引用。 一般說來, CDC中預(yù)期的類包括一個J2SE子集和一個完整的 CLDC超集,如圖4中所示:
就像使用所有的配置一樣,CDC有基層虛擬機的具體的必要條件。 根據(jù) CDC規(guī)范,基層虛擬機必須提供實現(xiàn)完整的 Java虛擬機的支持 。 如果虛擬機實現(xiàn)有一個用于激活設(shè)備的本地方法的界面,它必須兼容 JNI 1.1版本。 如果虛擬機實現(xiàn)有一個調(diào)試界面,它必須兼容 Java虛擬機調(diào)試界面 ( JVMDI )規(guī)范。 如果虛擬機有一個簡表界面,它必須兼容 Java虛擬機簡表界面 ( JVMPI )規(guī)范。 可見,為了實現(xiàn)這些功能,CDC肯定會變得很大,就不能稱其為K虛擬機了,因此,我們通常稱用于CDC的虛擬機為 CVM,這里的 C代表 compact、connected、consumer。
四、談?wù)凧2ME簡表
雖然配置為一組通用設(shè)備提供了小的 Java平臺,但是應(yīng)用程序開發(fā)者感興趣的是為一個個別的設(shè)備生產(chǎn)應(yīng)用程序,當(dāng)他們只是使用配置的話,他們編寫的應(yīng)用程序就會有一些欠缺。 配置必須滿足所有的設(shè)備的小的要求, 用戶界面、輸入機制和數(shù)據(jù)持久性有高度地設(shè)備具體性,每一種設(shè)備都有自己的用戶界面、輸入機制和數(shù)據(jù)存儲方法,這些往往不在配置所滿足的小要求的范圍之內(nèi)。
簡表為相同消費電子設(shè)備的不同的生產(chǎn)商提供了標(biāo)準化的 Java類庫, 事實上,雖然配置規(guī)范的開發(fā)由 Sun領(lǐng)導(dǎo),但是許多簡表規(guī)范仍將繼續(xù)由特殊設(shè)備的供應(yīng)商領(lǐng)導(dǎo)。 比如說, Motorola領(lǐng)導(dǎo)了行動電話和呼叫器簡表規(guī)范的開發(fā),又如 Palm 領(lǐng)導(dǎo) PDA簡表的開發(fā)。
現(xiàn)在,五個已知簡表已經(jīng)有了規(guī)范, 記住,每個簡表的責(zé)任都是為了完善配置的不足,下表列出了這五個簡表:
簡 表 完善配置
Mobile information devices profile (MIDP) 移動電話和呼叫器 CLDC
Personal digital assistant profile Palm和Handspring的PDA 設(shè)備 CLDC
Foundation profile 用于所有不需要GUI的CDC設(shè)備的標(biāo)準簡表 CDC
Personal profile 替代PersonalJava的Foundation完善的簡表 CDC
RMI profile 提供RMI的Foundation完善的簡表 CDC
現(xiàn)在我想談一談另一個Java類庫集,它現(xiàn)在差不多可以被認為是另一個簡表了。當(dāng)Sun為Palm開發(fā)個KVM時,他們需要一組類來 開發(fā)Palm的演示程序。這套類庫被封裝進 com.sun.kjava程序包, 在 CLDC早期的開發(fā)中,這些類被廣泛的使用來測試和演示 J2ME。因為 kjava是的允許應(yīng)用程序開發(fā)者使用 J2ME和 KVM開發(fā)應(yīng)用程序的類,所以它就被廣泛使用了。甚至到了今天,一個用于 PDA或更特殊一點的 Palm的簡表多已經(jīng)在開發(fā)中,許多開發(fā)者仍然希望使用 kjava類來開發(fā) PDA應(yīng)用程序。盡管 kjava類不被支持,并且僅僅用于設(shè)計測試程序或演示程序,并且它們將被一個即將到來的簡表所替代,但是開發(fā)者們?nèi)匀粺嶂杂谑褂盟鼇黹_發(fā)。
MIDP
Mobile Information Device Profile(移動信息設(shè)備簡表 ,簡稱 MIDP ),個實現(xiàn)的簡表,補充了 CLDC并且提供應(yīng)用程序語義和控件、用戶界面、持久存儲器、網(wǎng)絡(luò)和用于移動電話的計時器、雙通道呼叫器和其他無線電設(shè)備。 因為 MIDP和 CLDC兩者都有引用實現(xiàn),我們可以使用一個例程來研究一下這個簡表。
下面的例子是一個允許用戶輸入代表想知道的基金報價的代號的例子。應(yīng)用程序然后通過 HTTP接到一個金融網(wǎng)站,獲得基金報價,把價格儲存在一個數(shù)據(jù)庫,然后把價格返回給用戶。
// 到如需要的J2ME類
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
// 擴展MIDlet類來構(gòu)建我們的自定義MIDlet
public class FundTracker extends MIDlet implements
CommandListener {
file://顯示管理者變量
private Display display = null;
file://MIDlet的表單變量
private RequestForm reqForm = null;
file://MIDlet構(gòu)建器
public FundTracker () {
display = Display.getDisplay(this);
reqForm = new RequestForm("Fund Tracker");
reqForm.initForm();
reqForm.setCommandListener(this);
}
file://開始 MIDlet 應(yīng)用程序
protected void startApp() {
display.setCurrent(reqForm);
}
file://暫停 Midlet
protected void pauseApp() {
}
file://銷毀Midlet
protected void destroyApp(boolean unconditional) {
}
file://通過監(jiān)聽者響應(yīng)命令
public void commandAction(Command c, Displayable s) {
if (c == reqForm.getExitCommand()) {
destroyApp(false);
notifyDestroyed();
return;
}
if ((c == reqForm.getGetCommand()) &&
(reqForm.getSymField().getString().length() > 0)) {
getAndDisplayQuote();
} else
{
reqForm.getMsgString().setText("Symbol required");
}
}
file://儲存由#分開的成對的基金字符串和報價字符串
private void storeQuote (String fund, String newQuote) {
file://數(shù)據(jù)庫變量
RecordStore quoteDB = null;
try {
quoteDB = RecordStore.openRecordStore(
"FundQuotes", true);
byte[] data = (fund + "#" + newQuote).getBytes();
int size = data.length;
quoteDB.addRecord(data, 0, size);
quoteDB.closeRecordStore();
}
catch (Exception recordException) {
System.out.println("Unable to store quote and/or
use Fund Quote database.");
}
}
file://通過QuoteService類取回提交的代號表示的基金報價
private void getAndDisplayQuote(){
String fundSymbol = reqForm.getSymField().getString();
if (fundSymbol.length() > 0) {
String theQuote = QuoteService.getQuote(fundSymbol);
if (theQuote != null) {
storeQuote(fundSymbol, theQuote);
reqForm.getMsgString().setText(theQuote);
}
else
reqForm.getMsgString().setText("No quote" +
'\n' + "Check Symbol");
}
}
}
MIDP應(yīng)用程序稱為 MIDlet, 為了創(chuàng)建一個 MIDlet,你必須寫一個擴展基本 MIDlet類的類 (就像我們在上面代碼段中列出的那樣)。 這有點類似常見的 applet或 servlet。 MIDlets獨有的東西是把多個 MIDlet組成一個 MIDlet套件的能力。 這就允許 MIDlet在一個單獨的 JVM環(huán)境中共享資源,比如一個數(shù)據(jù)庫等等。 事實上,我們上面給出的例子還包括一個 MIDlet ( RetrieveQuote,見上段程序),用于取回所報價格。 當(dāng)MIDlet被請求時, MIDlet通過構(gòu)造程序?qū)嵗缓笳{(diào)用實例的 startApp()方法。
在 FundTracker例子中, MIDlet的用戶界面或顯示是由 Display類的一個實例管理的。 對于每個 MIDlet,只有一個顯示管理器實例。 所有可以顯示的項目,像屏幕或畫布(canvas),通過這個管理器都能夠成為可見的。因為行動電話和呼叫器能力的多樣化,又因為用于這些設(shè)備的應(yīng)用程序類型的差異, MIDP規(guī)范提供了兩種類型的用戶界面。一個可移植性稍差、明確設(shè)備、低水平的應(yīng)用程序接口,允許圖形元素精確的控制和放置。 這個接口類型是用于應(yīng)用程序特性比較典型的設(shè)備特別設(shè)計的,比如電子游戲。 一個可移植性稍好的、抽象的、的 GUI應(yīng)用程序接口,提供來用于商業(yè)應(yīng)用程序。
我們的例程使用的是的應(yīng)用程序接口和典型的用戶界面組件 (文本框,列表等等 ),是這類界面通用的。比如說,實際的表單和所有的小組件在一個單獨的文件中都已定義。 就像在代碼段一中列出的那樣,當(dāng) MIDlet創(chuàng)建時,一個表單的實例與 MIDlet關(guān)聯(lián)。 在調(diào)用 MIDlet startApp()方法的時候,通過 Display對象顯示表單。 使用一個用于表單的類,允許我們在我們簡單的報價檢索應(yīng)用程序中重新使用這個表單 ( RetrieveQuote )。為了清晰性和風(fēng)格,我們通過一個單獨的類來定義報價服務(wù)。 為了演示一般連接器結(jié)構(gòu)的能力,我們的報價服務(wù)類通過一個 Connector實例取回報價。
MIDP要求平臺設(shè)備提供一個機制用來儲存簡單的數(shù)據(jù)記錄,通過正常的平臺事件,比如重新啟動和電池更新維護系統(tǒng)的完整性。 MIDP稱一個持久數(shù)據(jù)庫為 RecordStore。 在我們的示例中, MIDlet打開并添加一條記錄到 " MutualFundQuotes " RecordStore。 正如我們的演示程序,能添加到 RecordStore中的一種類型的記錄是字節(jié)數(shù)組。 相同的 RecordStore是一個資源,它可以通過套件共享。 根據(jù) MIDP規(guī)范, 當(dāng) MIDlet從平臺中刪除后,RecordStore也會被從平臺中刪除。
PDA簡表
Palm公司是開發(fā)PDA簡表規(guī)范的領(lǐng)頭人, 這個簡表也是完善了 CLDC,在相當(dāng)長的一段時間內(nèi),它都將是 kjava類程序包的替代品。 Java規(guī)范建議這個 profile至少應(yīng)當(dāng)提供兩個核心功能片段: 一個用戶界面顯示工具包,適合于 "有限的尺寸和深度顯示 "和一個持久數(shù)據(jù)存儲器機制。 顯示工具包應(yīng)該是抽象窗口工具包的一個子集, 而持久機制將為應(yīng)用程序、數(shù)據(jù)、配置/環(huán)境信息提供簡單的數(shù)據(jù)存儲。
Foundation簡表
下面三種簡表不是非常常見, 這三種簡表的職責(zé)都是為了完善 CDC。 Personal和 RMI簡表實際上是 Foundation簡表的擴展。 Foundation簡表的任務(wù)是擔(dān)任一個基礎(chǔ)簡表,便于以后開發(fā)出來的提供圖形用戶接口、 網(wǎng)絡(luò)等功能的簡表附著在它之上。 除了用于基礎(chǔ)簡表, Foundation簡表還提供完整網(wǎng)絡(luò)的支持,不管有沒有使用圖形用戶接口。
Personal簡表
在當(dāng)前的規(guī)范需求下, Personal簡表提供下一代 PersonalJava環(huán)境。這個簡表允諾,提供互聯(lián)網(wǎng)連接性和 Web保真度以及一個能夠運行 Java applets的 GUI。
RMI簡表
回想一下 CDC配置為共享的、固定網(wǎng)絡(luò)連接信息設(shè)備提供小的 Java環(huán)境。 RMI簡表將通過提供 Java到 Java的RMI來協(xié)助提供更好的網(wǎng)絡(luò)連接性。 通過使用 J2SE ( 1.2.x或更高版本的 ) RMI,這個簡表將允許這些網(wǎng)絡(luò)設(shè)備與其他系統(tǒng)應(yīng)用程序交互操作 (這個系統(tǒng)不必也運行 J2ME )。
kjava類
正如前面提到的那樣, kjava類是初提供的一個供測試用的類,在 Palm設(shè)備上運行早期的 KVM和配置版本。 它們將被 PDA簡表代替。 kjava類擴展了 CLDC并且提供一個圖形用戶接口、 Palm數(shù)據(jù)庫訪問,簡單集合類和一個三角法計算器。
在代碼段2中,我使用 com.sun.kjava重寫了 MIDP FundTracker程序,讓它在 Palm上工作。 和前面的程序一樣,這個簡單的程序允許用戶輸入一個公基金代號并從WWW上的金融報價服務(wù)商那里取回報價。
kjava應(yīng)用程序被稱作 spotlet。 事實上,一個應(yīng)用程序可以由很多 spotlet組成,但是在任何時間只有一個 spotlet可以顯示在 Palm屏幕上。 在我們的例子中,我們創(chuàng)建一個基本 spotlet-- RequestFormSpotlet.java,為我們的兩個 spotlets子類提供用戶界面。代碼段 2擴展了基本的 RequestFormSpotlet以便得到并儲存一個報價。 RetrieveSpotlet也擴展了基本 RequestFormSpotlet并允許儲存的報價被取回(見圖)
代碼段2
import com.sun.kjava.*;
public final class FundSpotlet extends RequestFormSpotlet {
public static void main (String args[]) {
new FundSpotlet().draw();
}
private void draw() {
initForm();
setTitle("Fund Quote Requested");
}
public void penDown(int x, int y){
if (getExitButton().pressed(x,y)){
getGraphic().playSound(Graphics.SOUND_CONFIRMATION);
System.exit(0);
}
if (getSymField().pressed(x,y))
getSymField().setFocus();
if (getGetButton().pressed(x,y)) {
quoteRequested();
}
}
private void storeQuote (String fund, String newQuote) {
int dbType = 0x46554e44;
int dbCreator = 0x43415454;
com.sun.kjava.Database quoteDB;
try {
quoteDB = new com.sun.kjava.Database(dbType,
dbCreator, com.sun.kjava.Database.READWRITE);
if (!quoteDB .isOpen()) {
com.sun.kjava.Database.create(0, "MutualFundQuotes",
dbCreator, dbType, false);
quoteDB = new com.sun.kjava.Database(dbType,
dbCreator, com.sun.kjava.Database.READWRITE);
}
byte[] data = (fund + "#" + newQuote).getBytes();
quoteDB.addRecord(data);
quoteDB.close();
}
catch (Exception recordException) {
System.out.println("Unable to store quote and/or use
Mutual Fund Quote database.");
}
}
private void getAndDisplayQuote() {
String fundSymbol = getSymField().getText();
if (fundSymbol.length() > 0) {
String theQuote = QuoteService.getQuote(fundSymbol);
if (theQuote != null) {
storeQuote(fundSymbol, theQuote);
message(theQuote);
}
else
message("No quote. Check Symbol");
}
}
private void quoteRequested() {
message("");
getGraphic().playSound(Graphics.SOUND_STARTUP);
if ((getSymField().getText().length() > 0)) {
getAndDisplayQuote();
} else
{
message("Symbol required!");
}
}
}
在 RequestFormSpotlet程序中,類似于 MIDP中的 Display對象,單獨的 Graphics管理許多 spotlet用戶界面顯示。它考慮到了屏幕會被清除,顯示邊界會被建立。 不象 MIDlet,沒有屏幕或畫布對象來讓我們添加用戶界面小組件, 取而代之的是按鈕、文本字段等等,直接描畫在 spotlet上。 paint()方法利用圖形環(huán)境從的 Graphics在屏幕上顯示小組件。
我們的MIDP程序的 QuoteService類的大部分可以重新使用。 因為 kjava沒有象 MIDP中HttpConnection這樣特定的連接器界面,所以我們必須利用更多標(biāo)準的一般的連接器結(jié)構(gòu)表單獲取 HTTP鏈接。 為了做到這一點,使用代碼段 3中的代碼替換 getQuotePage()方法。注意注意使用 Connector,就像在 MIDP中我們使用 HttpConnection一樣。
代碼段3
private static String getQuotePage(String symbolString) {
StringBuffer quotePage = new StringBuffer();
int ch;
try {
InputStream in = Connector.openInputStream (
"testhttp://someurl/some_application?page=++&mode=fund&symbol="+
symbolString);
while ((ch = in.read()) > 0) {
quotePage.append((char)ch);
}
in.close();
return quotePage.toString();
} catch (IOException ex) {
System.out.println("Exception reading quote from
HTTP Connection");
return null;
}
}
Palm設(shè)備廣泛利用數(shù)據(jù)庫, 你的 Palm中的通訊簿、備忘錄和記事本應(yīng)用程序都與數(shù)據(jù)庫有關(guān)。 kjava程序包提供了一個非常小的 Database類,不僅可以創(chuàng)建并保持應(yīng)用程序數(shù)據(jù),而且可以訪問現(xiàn)有的數(shù)據(jù)庫。 如果你熟悉 Palm數(shù)據(jù)庫,你可能會對 kjava Database類提供的功能和信息感到失望。 然而,請再次記住, kjava只是一個演示的版本。
在我們的例子中,我們的 spotlet訪問一個 Palm數(shù)據(jù)庫 (如果不存在的話,則創(chuàng)建一個新的數(shù)據(jù)庫)來儲存公基金報價。每個 Palm數(shù)據(jù)庫都必須有名字、創(chuàng)建者 ID (一個 Palm登記的的標(biāo)識號 ) 和一個指定到某個單獨應(yīng)用程序的類型號。 試圖打開數(shù)據(jù)庫要通過嘗試創(chuàng)建一個帶有 ID信息的數(shù)據(jù)庫實例來實現(xiàn)。 就象 MIDP RecordStore,記錄被添加進 kjava數(shù)據(jù)庫,通過把一個字節(jié)數(shù)組當(dāng)成記錄添加到數(shù)據(jù)庫中的形式。
五、J2ME規(guī)范
在 J2ME內(nèi)還有很多子規(guī)范, J2ME的重要的部分如下:PersonalJava、K虛擬機 (KVM)、Java嵌入服務(wù)器以及 PersonalJava的兩個擴展規(guī)范: JavaPhone和 JavaTV應(yīng)用程序接口。 你可以想象, JavaPhone是一個定位于無線電智能電話和互聯(lián)網(wǎng)絡(luò)可視電話的應(yīng)用程序接口,而 JavaTV則滿足機頂盒市場的需求。
下面我想詳細的談一談以上的規(guī)范:
1、PersonalJava
PersonalJava應(yīng)用程序環(huán)境目標(biāo)是 Web連接消費設(shè)備----常常執(zhí)行來自網(wǎng)絡(luò)的小應(yīng)用程序。問題是 PersonalJava如何適合 J2ME的配置和簡表方案。 答案是 PersonalJava將被包容進 Connected Device Configuration中,終將被定義為 Personal簡表,即前面所談到的Personal簡表。
另一方面,有一段時間將有兩個 Java應(yīng)用程序接口為嵌入開發(fā)世界服務(wù): PersonalJava和 EmbeddedJava。 PersonalJava偎依在 J2ME大傘之下, 可為什么 EmbeddedJava不呢? EmbeddedJava不和 PersonalJava同在 J2ME內(nèi),是因為在 PersonalJava和 EmbeddedJava應(yīng)用程序之間有一個基本的差別。 PersonalJava應(yīng)用程序期望連接到某類網(wǎng)絡(luò)中下載并執(zhí)行小應(yīng)用程序。 按照這種觀點, PersonalJava設(shè)備就是一般用途的消費設(shè)備; 它們的能力可以被擴展。
相比之下, EmbeddedJava設(shè)備則慘了點。 它們執(zhí)行的功能都非常具體的,基本沒有必要提供下載新的代碼到 EmbeddedJava設(shè)備的能力。 Hence, PersonalJava設(shè)備使用可擴展 Java應(yīng)用程序接口; 而EmbeddedJava設(shè)備則沒有,因為沒有必要使用。
PersonalJava可以以兩種形式得到: 由原碼形式的,提供給那些對把PersonalJava移植到其他設(shè)備感興趣的開發(fā)者,那些已經(jīng)把 PersonalJava移植到某個具體的操作系統(tǒng)和處理機的組織提供二進制形式的 PersonalJava環(huán)境。有興趣探索 PersonalJava的開發(fā)者如果沒有二進制平臺也可以使用 PersonalJava模擬環(huán)境 ( PJEE )。 這個模擬器運行于 Solaris/SPARC或 Windows,并且在許多配置中可用。 這些多種多樣的配置基于“ look and feel”和類庫支持 (環(huán)境是否提供 PersonalJava規(guī)范中規(guī)定的限度的或的類庫)。PJEE包括類文件,一個應(yīng)用程序 launcher和一個 appletviewer (兩者都是為了調(diào)試功能并使其化)和其它的附帶的文件 (例如字體敘述文件)。
J2ME家族的另一位成員 JavaCheck實用程序,提供了 PersonalJava的補充支持。 你把應(yīng)用程序傳過 JavaCheck,它將告訴你你的應(yīng)用程序在一個 PersonalJava環(huán)境中能否順利地執(zhí)行。 JavaCheck檢查類之間的依賴關(guān)系,如果應(yīng)用程序調(diào)用了一個在 PersonalJava不可用的應(yīng)用程序接口,它就會給出一個警報信號。 (據(jù)我所知,目前有兩種JavaCheck的版本可用,一個是用于檢驗 PersonalJava 1.0版應(yīng)用程序,另一個用于檢驗 1.1.x版程序。 當(dāng)前的 PersonalJava應(yīng)用程序接口規(guī)范是 1.2,用于這一版本的 JavaCheck還沒有。 讀者請去Sun相關(guān)網(wǎng)站去看看( http : file://java.sun.com/products/personaljava)。
2、KVM
前面我也說過,KVM是用于 J2ME平臺小的虛擬機,并且是用于CLDC配置的虛擬機。可是J2ME應(yīng)用程序并不一定非要使用 KVM,J2ME技術(shù)可以使用任何虛擬機,不過至少應(yīng)當(dāng)有 KVM這樣的功能。
為了滿足基于KVM的設(shè)備一般只有狹小的內(nèi)存空間和有限的處理能力的事實, KVM使用 C編寫 (它不是現(xiàn)有的VM改進了的以后的產(chǎn)品)。 此外, KVM是模塊化的, 也就是說,它是由模塊構(gòu)建的,當(dāng)某個模塊實現(xiàn)了預(yù)先設(shè)定的目標(biāo)后,就可以很容易地把這一模塊卸載。 可選的某塊包括: 大的數(shù)據(jù)類型 ( long、 float和 double ),多維數(shù)組、類文件驗證等。
KVM的本地界面以輕便性為原則構(gòu)建,所以在KVM中任務(wù)切換不依賴硬件產(chǎn)生的記時器中斷,因此在這種意思上來說不是搶先式。任務(wù)切換發(fā)生在虛擬機執(zhí)行了一個預(yù)設(shè)編號的字節(jié)碼之后。 并且, KVM的無用單元收集利用一個標(biāo)記清掃(mark and sweep)算法來實現(xiàn)無用單元釋放。 因此,對象引用是直接的,就像標(biāo)準 Java一樣。
當(dāng)然,除了虛擬機以外還有許多可用的執(zhí)行環(huán)境,在小型設(shè)備中,虛擬機必須要么被擴展,要么在附加工具協(xié)助下提供一個更加完整的運行期環(huán)境,正是這個原因, KVM需要附帶的工具,比如說, JavaCodeCompact工具提供了預(yù)鏈接和預(yù)加載類, 允許Java類被直接地鏈接進虛擬機中。((設(shè)備上所有的應(yīng)用程序使用的類 can直接地嵌入虛擬機。)
KVM一個可選的附件就是 Java Application Manager ( Java應(yīng)用程序管理器,簡稱 JAM )。JAM的工作就是處理下載、安裝、執(zhí)行和卸載 CLDC設(shè)備上的應(yīng)用程序的細節(jié)問題,因為資源有限,在CLDC設(shè)備上有可能不存在這些功能。JAM也處理更新安裝應(yīng)用程序的操作。(如果更新過程失敗,它甚至可以重新使用舊的應(yīng)用程序。 )
3、Java Embedded Server(Java嵌入服務(wù)器)
Java Embedded Server( Java嵌入服務(wù)器,簡稱 JES),在 PersonalJava基礎(chǔ)上建立,是一個用于嵌入式網(wǎng)絡(luò)設(shè)備的運行期環(huán)境。為了理解 JES,你必須理解兩個核心概念:服務(wù)和服務(wù)空間結(jié)構(gòu)。后者是前者的容器。服務(wù)程序是運行于一個 JES服務(wù)器上的組件化程序;服務(wù)空間結(jié)構(gòu)是為服務(wù)程序提供生命周期 支持的環(huán)境。
技術(shù)上說,服務(wù)程序是界面的實現(xiàn),事實上,它是一個實現(xiàn)特定活動的Java類集合。比如說,假如把 JES配置為一個家庭的氣候控制系統(tǒng)的服務(wù)器,可以把從模數(shù)轉(zhuǎn)換器讀到的溫度數(shù)據(jù)放進一個數(shù)據(jù)組件程序中。我就可以稱這個組件為ReadThermostats服務(wù)程序。
在 JES的領(lǐng)域,服務(wù)的封裝媒介稱為 bundle。簡單地說,bundle就是一個帶有特殊內(nèi)容的JAR文件。服務(wù)程序和bundle之間有一對一關(guān)系,一個bundle帶有一個服務(wù)程序。服務(wù)程序和 bundle之間有一對一關(guān)系,一個 bundle帶有一個服務(wù)程序。可這也不一定,一個 bundle可以設(shè)置多個服務(wù)程序索引 (注意, JES提供的所有的核心服務(wù),每個 bundle中只有一個 )。
正如前面提到的那樣,服務(wù)空間的一項工作就是管理服務(wù)程序的生命周期,這個工作的很大的部分包括解決服務(wù)隸屬關(guān)系。bundle內(nèi)容的一個重要的部分是bundle服務(wù)的依賴信息。所以,當(dāng)服務(wù)空間打開一個bundle安裝它的服務(wù)時,服務(wù)空間就可以確定外部需要什么服務(wù)。而且,一個服務(wù)的依賴關(guān)系并不是靜止不變的,它們可以隨某些事件改變。比如說當(dāng)服務(wù)程序更新時的變化就是一個很好的例子。一個服務(wù)的新的版本可以添加或去除依賴關(guān)系。服務(wù)空間跟蹤并解決這樣的動態(tài)依賴關(guān)系。如果服務(wù)空間處理所有服務(wù)程序的生命周期,這就暗示了服務(wù)空間被賦予知曉一切的能力,那就是說,它能夠推論結(jié)構(gòu)、依賴、安裝的細微差別等所有它負責(zé)的服務(wù)。服務(wù)空間通過在 bundle內(nèi)伴隨服務(wù)的 Java代碼模塊處理一些任務(wù),這些模塊被稱作 wizard(向?qū)ВES向?qū)歉鶕?jù)它們完成的任務(wù)命名的:
Dependencies -向?qū)Ц嬖V調(diào)用者一個bundle依賴關(guān)系是什么。
Installer-向?qū)幚韇undle中服務(wù)的安裝和刪除操作。
Activator -向?qū)е廊绾螁雍徒K止服務(wù)。
Updater -向?qū)Э丶耣undle中的服務(wù)。(更新向?qū)Р粌H知道更新一個服務(wù),而且知道在何時和什么情況下更新服務(wù)。 )
About -這個向?qū)В拖袼Q意味的那樣,返回關(guān)于 bundle內(nèi)容的信息。
Dispatcher -這是一種元向?qū)В╩eta-wizard)。服務(wù)空間調(diào)用dispatcher向?qū)Фㄎ灰粋€bundle的其他向?qū)А?
當(dāng)一個 JES服務(wù)器啟動的時候,服務(wù)空間并不是完全沒有啟動服務(wù)。JES定義一組核心服務(wù)(可選),這些都是任何 JES服務(wù)器的組成部分。這些核心服務(wù)包含:
HTTP服務(wù)
日志 -記錄錯誤和事件日志
日期 -精確到秒的日期/時間服務(wù)
連接管理器 -提供網(wǎng)絡(luò)服務(wù)和Socket綁定,也處理連接接收。
線程管理器 -管理服務(wù)器提供的線程。thread管理器支持線程池并允許有效使用線程上界的規(guī)范。
計劃程序 -提供未來的事件計劃安排 (可用于告訴服務(wù)器某某動作必須在某某事件發(fā)生 )
RMI
SNMP
控制臺 -提供遠程管理服務(wù)器功能
基于 HTTP的遠程應(yīng)用程序接口實現(xiàn)
基于 RMI的遠程應(yīng)用程序接口實現(xiàn)
如果你把服務(wù)空間結(jié)構(gòu)當(dāng)成 JavaBean中的容器的話, JES就變得容易理解了。在這種類比關(guān)系中,服務(wù)程序就相當(dāng) JavaBean。那么,正象組件容器提供一個環(huán)境供 JavaBeans實例化、運行一樣,服務(wù)空間就是以實例化的服務(wù)的聚集地。服務(wù)空間管理安裝、實例化、執(zhí)行、終止以及卸載服務(wù);它也提供應(yīng)用程序接口供服務(wù)交互作用。
到目前為止,大部分人都已非常熟悉 Java 2平臺,以及 Sun如何把 Java技術(shù)分成三個版本 (標(biāo)準版、袖珍版以及企業(yè)版),Sun 在1999年6月時推出了 Java 2袖珍版 (J2ME)來滿足消費電子和嵌入設(shè)備的需要。J2ME是為了那些使用有限的能源、有限的網(wǎng)絡(luò)連接 (常常是無線連接)以及有限圖形用戶界面能力的設(shè)備開發(fā)的。它初的目標(biāo)是 16位或 32位處理器,16 MHz時鐘頻率, 512K或更少內(nèi)存的設(shè)備。乍一看之下, J2ME就像一個沒有綁定明顯主題的松散的應(yīng)用程序接口和技術(shù)規(guī)范。我們想通過說它不是什么東西的方法來描述它,它不是一組用于臺式機 Java應(yīng)用程序規(guī)范,如果你再觀察仔細一些,你會發(fā)現(xiàn)所有的 J2ME組件都圍繞一個中心,這些中心被稱為configuration(配置 ,Sun的市場營銷資料也稱它們 design centers,設(shè)計中心),它們中間的每一個都是用于消費電子和嵌入設(shè)備的特別的類。
Connected limited device configuration(有限連接設(shè)備配置,簡稱 CLDC ) 這個配置定義了 Java應(yīng)用程序接口以及支持手持設(shè)備的技術(shù),就像 Sun的文檔中所描述的那樣, " devices that you hold in your hand(你握在手中的設(shè)備) " Palm序列手持設(shè)備可能是這一領(lǐng)域的設(shè)備的的例子,特別是它有開發(fā) CLDC的功能以及 Palm設(shè)備運行期系統(tǒng)可用。
Connected device configuration(連接設(shè)備配置 CDC ) 這個配置定義支持象 Sun文檔中所說, " devices that you plug into plug into the wall(你插入墻的設(shè)備)的設(shè)備的應(yīng)用程序接口和技術(shù),這樣的設(shè)備的一個例子可能就是機頂盒。
這兩種配置不同的地方就在于它們應(yīng)用于的裝置的能力, CLDC設(shè)備的處理器能力有限 (與臺式機系統(tǒng)比較 ),并且存儲器大小一般也只在128 KB到 512 KB之間, 與此同時,CDC系統(tǒng)就不同了,它可能有 32位或 64位處理器,以及有限的存儲容量,不過它的下限也得超過512K。 它遵循的原則就是,每個不同的能力硬件的配置都將被不同的虛擬機支持。 基于 CDC的系統(tǒng)使用一個功能強勁的虛擬機,而基于 CLDC系統(tǒng)的使用 KVM 。
每個配置代表一種低水平的,基本的應(yīng)用程序接口,在這兩個相似基礎(chǔ)之上是 profile(簡表),用于特殊設(shè)備的額外的應(yīng)用程序接口。 我想通過看一張來自SUN提供的文檔中的圖表 (參見圖 1 )來解釋這其中的關(guān)系。
J2ME的體系結(jié)構(gòu)被橫向地分成三層,縱向分成兩部分。配置包括一個控制配置核心類的虛擬機, 具體的簡表位于每個配置之上。
J2ME現(xiàn)在定義兩個配置, Connected Device configuration(連接設(shè)備配置 CDC )和限制性更強的 Connected Limited Device Configuration (有限連接設(shè)備配置)。 簡表的實現(xiàn)是 Java應(yīng)用程序接口的一個集合,用于適應(yīng)被定義配置的應(yīng)用程序接口提供的服務(wù),簡表是一個完整的運行環(huán)境,一個在簡表上執(zhí)行的應(yīng)用程序不需要額外的支持類。
J2ME沒有定義滿足這兩種配置的標(biāo)準化用戶接口,Sun也承認現(xiàn)在的消費設(shè)備多種多樣,用戶界面也各不一樣,所以定義一個可用于所有用戶的界面是一場失敗的戰(zhàn)爭。 J2ME中的用戶界面定義在簡表中。
二、J2ME的體系結(jié)構(gòu)
現(xiàn)在個人計算機系統(tǒng)的數(shù)量和種類已經(jīng)發(fā)展到無法控制的地步,請你想一想,你編寫的程序運行在“信息家電”舞臺的情景吧,這些信息家電包括呼叫器,行動電話,像Palm這樣的個人數(shù)字助手(PDA),電視機頂盒,POS終端以及其他的消費電子設(shè)備。現(xiàn)在全世界上光是手提電話生產(chǎn)商就有許多,更不用說別的家電設(shè)備了,而且每一種家電設(shè)備又有不同的特性和界面。所以,你可以想到, Java應(yīng)用程序的輕便性以及能夠解決開發(fā)這么許多不同的設(shè)備程序的能力,使大家對J2ME有很大的期許。當(dāng)然,為了更好的開發(fā)這些信息家電,就要求把Java的精髓壓縮進一個非常小的程序包中,這就是J2ME。
J2ME是一種通過許多部件和規(guī)范的技術(shù), 這眾多的部件和規(guī)范幫助 J2ME來滿足這眾多的消費產(chǎn)品的不同的需要。和所有的爪哇程式語言技術(shù)一樣,在它的核心屬于一種虛擬機。 就像使用所有 Java技術(shù)一樣,J2ME的核心也在一種虛擬機中。 初,用于 J2ME應(yīng)用程序虛擬機的被稱作 Kilobyte virtual machine或簡稱 KVM。就像它名稱的含義, KVM比較小,通常只有 128K或更少。這比起我們通常了解和使用的 Java 2標(biāo)準版 Java虛擬機 ( JVM )的 32 MB來說就小得多了。
用于連接虛擬機的是一系列配置和簡表,它們提供了用于特定 J2ME環(huán)境的類應(yīng)用程序接口(見圖二)。 每個配置和簡表處理一般或具體的消費產(chǎn)品,配置和簡表規(guī)范是由多種多樣的設(shè)備生產(chǎn)商和用戶共同開發(fā)并建立的。配置是用于一組通用設(shè)備的小的 Java平臺, 常常歸為一種橫向的設(shè)備分組,相對來說,橫向分組設(shè)備是那些共享相同的內(nèi)存安排,通信帶寬,能量需求以及用戶能力的設(shè)備,一般認為配置能夠提供這眾多的設(shè)備的所有需求。
Java虛擬機是 J2ME技術(shù)的核心,但是配置和簡表提供特殊環(huán)境的類應(yīng)用程序接口。配置是用于一組通用設(shè)備的小的 Java平臺,而簡表則為具體的設(shè)備家族或特別的應(yīng)用程序提供更具體的能力。
J2ME領(lǐng)域的新的開發(fā)者常常被這些事實困惑的, 事實上, Sun的個配置(現(xiàn)在只是一種配置的引用實現(xiàn) )帶有稱為 KVM的虛擬機引用實現(xiàn), KVM滿足配置的虛擬機的必要條件。然而, Sun的 KVM也可以被另外一個虛擬機所代替,現(xiàn)在, 正是因為配置和虛擬機結(jié)合得有點緊密,因此導(dǎo)致了這么多的混亂。
另一方面,簡表完善了 配置,為某個具體的設(shè)備家族或某個具體的工業(yè)片段應(yīng)用程序提供更高的性能。 換言之, 簡表為具體的縱向市場的設(shè)備比如說行動電話提供更多的性能。這里的關(guān)鍵就是 簡表必須完善 配置, 沒有 配置和虛擬機提供核心類應(yīng)用程序接口和運行期環(huán)境的話,簡表也不會工作。
通常,簡表為一種給定的垂直分組設(shè)備提供用戶界面、輸入法、持久性機制。這類 簡表被認為是發(fā)展這些設(shè)備應(yīng)用程序的完整的工具包。我們見到多的應(yīng)用程序簡表的例子就移動電話簡表和個人數(shù)字助手(PDA)簡表,其他簡表為范圍寬廣的設(shè)備提供非常特殊的功能或應(yīng)用程序可移植性,這方面的例子就是提供遠程方法調(diào)用 ( RMI )功能的簡表和提供統(tǒng)一銀行事務(wù)的簡表。
虛擬機、 配置、 簡表…你是不是已經(jīng)被搞迷糊了? 如果這樣的話,我們就來簡化一下 J2ME體系結(jié)構(gòu)吧。 如果你想為小型信息家電編寫 Java應(yīng)用程序的話,你就需要兩個前提:一個 配置和至少一個 簡表。 現(xiàn)在, 一般是配置捆綁了虛擬機和一套針對你的平臺所能夠用的橫向分組設(shè)備的Java類庫。其次,你至少還需要一個 簡表來為你的平臺提供附加的 Java類,這個 簡表通常會為你的設(shè)備提供用戶界面、輸入和數(shù)據(jù)庫類。有了這兩個前提,你就了使用 Java為你的設(shè)備編寫應(yīng)用程序的基本的J2ME環(huán)境。
三、詳細談?wù)凧2ME配置
J2ME可以在好幾個不同的配置中進行配置。就像先前提到的,每個配置為一組通用設(shè)備提供小的 Java平臺,到目前為止,只有兩種配置規(guī)范。通過 Java規(guī)范定義的這兩種配置是 Connected Limited Device Configuration (有限連接設(shè)備配置, CLDC )和 Connected Device Configuration (連接設(shè)備配置 CDC )。
CLDC是為使用較小的存儲容量的設(shè)備設(shè)計的 (參見圖3 )。 CLDC用于內(nèi)存在128到 512K之間的消費電子設(shè)備, 這一類別中典型代表的設(shè)備包含呼叫器、行動電話、PDA和POS終端;而另一方面, CDC用于比 PC機小但是具有比 512K內(nèi)存多的設(shè)備,這一類設(shè)備包括互聯(lián)網(wǎng)絡(luò)電視系統(tǒng)、機頂盒、POS系統(tǒng)、汽車導(dǎo)航以及娛樂系統(tǒng)。一般來說, CDC使小型設(shè)備只要具有少量的資源,至少比臺式機要少的資源就能進行Java編程,而CLDC使小型設(shè)備所擁有的資源只要比一張智能卡多一點就可以進行Java編程了。
J2ME有兩個配置CLDC和 CDC,CLDC是為使用較小的存儲容量的設(shè)備設(shè)計的,而CDC用于比 PC機小但是具有比 512K內(nèi)存多的設(shè)備。
除了在容量大小和能力上對虛擬機規(guī)定了必要條件,配置還規(guī)定了類應(yīng)用程序接口要包含常見的 java.io、 java.net、 java.util和 java.lang包,配置可能還要包括其他需要的程序包。
CLDC
CLDC起源可以追溯到1999年JavaOne大會上介紹的Sun的個袖珍版 Java和個 KVM以及相關(guān)的類庫,雖然 CLDC和所有的配置都滿足成為虛擬機的條件,可它本身還不是虛擬機,CLDC的引用實現(xiàn)只是包含在當(dāng)前的分布中的 KVM。
根據(jù)規(guī)范中所說,運行 CLDC的設(shè)備應(yīng)該有 512K或更少的內(nèi)存空間、一個有限的電源供給 (通常是使用電池)、有限的或斷斷續(xù)續(xù)的網(wǎng)絡(luò)連接性 ( 9600 bps或更少 )以及多樣化的用戶界面甚至沒有用戶界面。 通常說來,這個配置是為個人化的、移動的、有限連接信息設(shè)備而設(shè)計,比如呼叫器、移動電話和 PDA等。
與 J2SE相比, CLDC缺少下列所說的這些特征:
AWT(抽象窗口開發(fā)包), Swing或其他圖形庫
用戶定義類裝載器
類實例的終化
弱的引用
RMI
Reflection(映射)
CLDC有四個包: java.lang、 java.util、 java.io和 javax.microedition。 除了 microedition包以外,其他的這幾個包都是J2SE包的核心子集,CLDC采用這些J2SE類庫,但是把其中一些在微型設(shè)備中用不到類、屬性、方法去掉了。因此 CLDC類庫有許多細微的差別。 如果您想研究J2SE和 CLDC類庫之間的差別,請參閱相關(guān)文檔,在此就不詳細說明了。
想要理解為什么CLDC去除這么多J2SE中重要的類和特征,請回想一下與 CLDC相關(guān)的兩條基本原理。首先,它只有 512K的內(nèi)存空間, 而像RMI和映射需要的內(nèi)存太大了。 其次,配置必須滿足為一組通用設(shè)備提供小的 Java平臺。 在個人移動信息設(shè)備領(lǐng)域中,許多系統(tǒng)都不能支持 J2SE中的眾多的特征。 例如,許多消費電子產(chǎn)品不能支持浮點數(shù); 因此 Float(浮點類)和 Double(雙精度類)就被刪除了。 再看另外一個例子,許多系統(tǒng)沒有或不提供訪問一個文件系統(tǒng)的功能或權(quán)限。 因此與文件有關(guān)的類也被丟棄了。又如,錯誤處理是一個代價非常高的過程處理,在許多消費電子設(shè)備中,故障恢復(fù)是很難的甚至是不可能的。 所以在 CLDC中,許多錯誤處理類也被刪除了。
java.microedition程序包提供了一個一般的結(jié)構(gòu)來替代許多 J2SE網(wǎng)絡(luò)輸入/輸出類。 CLDC一般連接器結(jié)構(gòu)還定義了一個 Connector類,允許許多不同類型的連接能夠使用靜態(tài)方法,下表列出使用同一個Connector類創(chuàng)建和打開五種不同類型的連接的方法:
HTTP Connector.open("http://www.xyz.com");
套接字 Connector.open("socket://111.222.111.222:9000");
通訊端口 Connector.open("comm:1;baudrate=9600");
數(shù)據(jù)報 Connector.open("datagram://111.222.111.222");
文件 Connector.open("file:/xyz.dat");
一般連接器結(jié)構(gòu)提供給應(yīng)用程序開發(fā)者一個到通用低水平硬件的簡單的映射表。成功執(zhí)行 open語句將返回一個實現(xiàn)一般連接界面的對象。
CDC
CDC涵蓋了個人電腦與有至少 512K內(nèi)存的小型設(shè)備之間的中間地帶。現(xiàn)在,這一類設(shè)備通常是共享的、固定的 (不用移動)網(wǎng)絡(luò)連接信息設(shè)備,像電視機機頂盒,網(wǎng)絡(luò)電視系統(tǒng)、互聯(lián)網(wǎng)電話與汽車導(dǎo)航/娛樂系統(tǒng)等等。
首先,CDC基于 J2SE 1.3應(yīng)用程序接口,包含所有定義在CLDC規(guī)范(包括 javax.microedition程序包)中的Java語言應(yīng)用程序接口。與CLDC相比, CLDC所有缺少的特性和類在 CDC中都被補齊,包含映射、終化、所有的錯誤處理類、浮點數(shù)、屬性、輸入/輸出 ( File、 FileInputStream等等 )和弱的引用。 一般說來, CDC中預(yù)期的類包括一個J2SE子集和一個完整的 CLDC超集,如圖4中所示:
就像使用所有的配置一樣,CDC有基層虛擬機的具體的必要條件。 根據(jù) CDC規(guī)范,基層虛擬機必須提供實現(xiàn)完整的 Java虛擬機的支持 。 如果虛擬機實現(xiàn)有一個用于激活設(shè)備的本地方法的界面,它必須兼容 JNI 1.1版本。 如果虛擬機實現(xiàn)有一個調(diào)試界面,它必須兼容 Java虛擬機調(diào)試界面 ( JVMDI )規(guī)范。 如果虛擬機有一個簡表界面,它必須兼容 Java虛擬機簡表界面 ( JVMPI )規(guī)范。 可見,為了實現(xiàn)這些功能,CDC肯定會變得很大,就不能稱其為K虛擬機了,因此,我們通常稱用于CDC的虛擬機為 CVM,這里的 C代表 compact、connected、consumer。
四、談?wù)凧2ME簡表
雖然配置為一組通用設(shè)備提供了小的 Java平臺,但是應(yīng)用程序開發(fā)者感興趣的是為一個個別的設(shè)備生產(chǎn)應(yīng)用程序,當(dāng)他們只是使用配置的話,他們編寫的應(yīng)用程序就會有一些欠缺。 配置必須滿足所有的設(shè)備的小的要求, 用戶界面、輸入機制和數(shù)據(jù)持久性有高度地設(shè)備具體性,每一種設(shè)備都有自己的用戶界面、輸入機制和數(shù)據(jù)存儲方法,這些往往不在配置所滿足的小要求的范圍之內(nèi)。
簡表為相同消費電子設(shè)備的不同的生產(chǎn)商提供了標(biāo)準化的 Java類庫, 事實上,雖然配置規(guī)范的開發(fā)由 Sun領(lǐng)導(dǎo),但是許多簡表規(guī)范仍將繼續(xù)由特殊設(shè)備的供應(yīng)商領(lǐng)導(dǎo)。 比如說, Motorola領(lǐng)導(dǎo)了行動電話和呼叫器簡表規(guī)范的開發(fā),又如 Palm 領(lǐng)導(dǎo) PDA簡表的開發(fā)。
現(xiàn)在,五個已知簡表已經(jīng)有了規(guī)范, 記住,每個簡表的責(zé)任都是為了完善配置的不足,下表列出了這五個簡表:
簡 表 完善配置
Mobile information devices profile (MIDP) 移動電話和呼叫器 CLDC
Personal digital assistant profile Palm和Handspring的PDA 設(shè)備 CLDC
Foundation profile 用于所有不需要GUI的CDC設(shè)備的標(biāo)準簡表 CDC
Personal profile 替代PersonalJava的Foundation完善的簡表 CDC
RMI profile 提供RMI的Foundation完善的簡表 CDC
現(xiàn)在我想談一談另一個Java類庫集,它現(xiàn)在差不多可以被認為是另一個簡表了。當(dāng)Sun為Palm開發(fā)個KVM時,他們需要一組類來 開發(fā)Palm的演示程序。這套類庫被封裝進 com.sun.kjava程序包, 在 CLDC早期的開發(fā)中,這些類被廣泛的使用來測試和演示 J2ME。因為 kjava是的允許應(yīng)用程序開發(fā)者使用 J2ME和 KVM開發(fā)應(yīng)用程序的類,所以它就被廣泛使用了。甚至到了今天,一個用于 PDA或更特殊一點的 Palm的簡表多已經(jīng)在開發(fā)中,許多開發(fā)者仍然希望使用 kjava類來開發(fā) PDA應(yīng)用程序。盡管 kjava類不被支持,并且僅僅用于設(shè)計測試程序或演示程序,并且它們將被一個即將到來的簡表所替代,但是開發(fā)者們?nèi)匀粺嶂杂谑褂盟鼇黹_發(fā)。
MIDP
Mobile Information Device Profile(移動信息設(shè)備簡表 ,簡稱 MIDP ),個實現(xiàn)的簡表,補充了 CLDC并且提供應(yīng)用程序語義和控件、用戶界面、持久存儲器、網(wǎng)絡(luò)和用于移動電話的計時器、雙通道呼叫器和其他無線電設(shè)備。 因為 MIDP和 CLDC兩者都有引用實現(xiàn),我們可以使用一個例程來研究一下這個簡表。
下面的例子是一個允許用戶輸入代表想知道的基金報價的代號的例子。應(yīng)用程序然后通過 HTTP接到一個金融網(wǎng)站,獲得基金報價,把價格儲存在一個數(shù)據(jù)庫,然后把價格返回給用戶。
// 到如需要的J2ME類
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
// 擴展MIDlet類來構(gòu)建我們的自定義MIDlet
public class FundTracker extends MIDlet implements
CommandListener {
file://顯示管理者變量
private Display display = null;
file://MIDlet的表單變量
private RequestForm reqForm = null;
file://MIDlet構(gòu)建器
public FundTracker () {
display = Display.getDisplay(this);
reqForm = new RequestForm("Fund Tracker");
reqForm.initForm();
reqForm.setCommandListener(this);
}
file://開始 MIDlet 應(yīng)用程序
protected void startApp() {
display.setCurrent(reqForm);
}
file://暫停 Midlet
protected void pauseApp() {
}
file://銷毀Midlet
protected void destroyApp(boolean unconditional) {
}
file://通過監(jiān)聽者響應(yīng)命令
public void commandAction(Command c, Displayable s) {
if (c == reqForm.getExitCommand()) {
destroyApp(false);
notifyDestroyed();
return;
}
if ((c == reqForm.getGetCommand()) &&
(reqForm.getSymField().getString().length() > 0)) {
getAndDisplayQuote();
} else
{
reqForm.getMsgString().setText("Symbol required");
}
}
file://儲存由#分開的成對的基金字符串和報價字符串
private void storeQuote (String fund, String newQuote) {
file://數(shù)據(jù)庫變量
RecordStore quoteDB = null;
try {
quoteDB = RecordStore.openRecordStore(
"FundQuotes", true);
byte[] data = (fund + "#" + newQuote).getBytes();
int size = data.length;
quoteDB.addRecord(data, 0, size);
quoteDB.closeRecordStore();
}
catch (Exception recordException) {
System.out.println("Unable to store quote and/or
use Fund Quote database.");
}
}
file://通過QuoteService類取回提交的代號表示的基金報價
private void getAndDisplayQuote(){
String fundSymbol = reqForm.getSymField().getString();
if (fundSymbol.length() > 0) {
String theQuote = QuoteService.getQuote(fundSymbol);
if (theQuote != null) {
storeQuote(fundSymbol, theQuote);
reqForm.getMsgString().setText(theQuote);
}
else
reqForm.getMsgString().setText("No quote" +
'\n' + "Check Symbol");
}
}
}
MIDP應(yīng)用程序稱為 MIDlet, 為了創(chuàng)建一個 MIDlet,你必須寫一個擴展基本 MIDlet類的類 (就像我們在上面代碼段中列出的那樣)。 這有點類似常見的 applet或 servlet。 MIDlets獨有的東西是把多個 MIDlet組成一個 MIDlet套件的能力。 這就允許 MIDlet在一個單獨的 JVM環(huán)境中共享資源,比如一個數(shù)據(jù)庫等等。 事實上,我們上面給出的例子還包括一個 MIDlet ( RetrieveQuote,見上段程序),用于取回所報價格。 當(dāng)MIDlet被請求時, MIDlet通過構(gòu)造程序?qū)嵗缓笳{(diào)用實例的 startApp()方法。
在 FundTracker例子中, MIDlet的用戶界面或顯示是由 Display類的一個實例管理的。 對于每個 MIDlet,只有一個顯示管理器實例。 所有可以顯示的項目,像屏幕或畫布(canvas),通過這個管理器都能夠成為可見的。因為行動電話和呼叫器能力的多樣化,又因為用于這些設(shè)備的應(yīng)用程序類型的差異, MIDP規(guī)范提供了兩種類型的用戶界面。一個可移植性稍差、明確設(shè)備、低水平的應(yīng)用程序接口,允許圖形元素精確的控制和放置。 這個接口類型是用于應(yīng)用程序特性比較典型的設(shè)備特別設(shè)計的,比如電子游戲。 一個可移植性稍好的、抽象的、的 GUI應(yīng)用程序接口,提供來用于商業(yè)應(yīng)用程序。
我們的例程使用的是的應(yīng)用程序接口和典型的用戶界面組件 (文本框,列表等等 ),是這類界面通用的。比如說,實際的表單和所有的小組件在一個單獨的文件中都已定義。 就像在代碼段一中列出的那樣,當(dāng) MIDlet創(chuàng)建時,一個表單的實例與 MIDlet關(guān)聯(lián)。 在調(diào)用 MIDlet startApp()方法的時候,通過 Display對象顯示表單。 使用一個用于表單的類,允許我們在我們簡單的報價檢索應(yīng)用程序中重新使用這個表單 ( RetrieveQuote )。為了清晰性和風(fēng)格,我們通過一個單獨的類來定義報價服務(wù)。 為了演示一般連接器結(jié)構(gòu)的能力,我們的報價服務(wù)類通過一個 Connector實例取回報價。
MIDP要求平臺設(shè)備提供一個機制用來儲存簡單的數(shù)據(jù)記錄,通過正常的平臺事件,比如重新啟動和電池更新維護系統(tǒng)的完整性。 MIDP稱一個持久數(shù)據(jù)庫為 RecordStore。 在我們的示例中, MIDlet打開并添加一條記錄到 " MutualFundQuotes " RecordStore。 正如我們的演示程序,能添加到 RecordStore中的一種類型的記錄是字節(jié)數(shù)組。 相同的 RecordStore是一個資源,它可以通過套件共享。 根據(jù) MIDP規(guī)范, 當(dāng) MIDlet從平臺中刪除后,RecordStore也會被從平臺中刪除。
PDA簡表
Palm公司是開發(fā)PDA簡表規(guī)范的領(lǐng)頭人, 這個簡表也是完善了 CLDC,在相當(dāng)長的一段時間內(nèi),它都將是 kjava類程序包的替代品。 Java規(guī)范建議這個 profile至少應(yīng)當(dāng)提供兩個核心功能片段: 一個用戶界面顯示工具包,適合于 "有限的尺寸和深度顯示 "和一個持久數(shù)據(jù)存儲器機制。 顯示工具包應(yīng)該是抽象窗口工具包的一個子集, 而持久機制將為應(yīng)用程序、數(shù)據(jù)、配置/環(huán)境信息提供簡單的數(shù)據(jù)存儲。
Foundation簡表
下面三種簡表不是非常常見, 這三種簡表的職責(zé)都是為了完善 CDC。 Personal和 RMI簡表實際上是 Foundation簡表的擴展。 Foundation簡表的任務(wù)是擔(dān)任一個基礎(chǔ)簡表,便于以后開發(fā)出來的提供圖形用戶接口、 網(wǎng)絡(luò)等功能的簡表附著在它之上。 除了用于基礎(chǔ)簡表, Foundation簡表還提供完整網(wǎng)絡(luò)的支持,不管有沒有使用圖形用戶接口。
Personal簡表
在當(dāng)前的規(guī)范需求下, Personal簡表提供下一代 PersonalJava環(huán)境。這個簡表允諾,提供互聯(lián)網(wǎng)連接性和 Web保真度以及一個能夠運行 Java applets的 GUI。
RMI簡表
回想一下 CDC配置為共享的、固定網(wǎng)絡(luò)連接信息設(shè)備提供小的 Java環(huán)境。 RMI簡表將通過提供 Java到 Java的RMI來協(xié)助提供更好的網(wǎng)絡(luò)連接性。 通過使用 J2SE ( 1.2.x或更高版本的 ) RMI,這個簡表將允許這些網(wǎng)絡(luò)設(shè)備與其他系統(tǒng)應(yīng)用程序交互操作 (這個系統(tǒng)不必也運行 J2ME )。
kjava類
正如前面提到的那樣, kjava類是初提供的一個供測試用的類,在 Palm設(shè)備上運行早期的 KVM和配置版本。 它們將被 PDA簡表代替。 kjava類擴展了 CLDC并且提供一個圖形用戶接口、 Palm數(shù)據(jù)庫訪問,簡單集合類和一個三角法計算器。
在代碼段2中,我使用 com.sun.kjava重寫了 MIDP FundTracker程序,讓它在 Palm上工作。 和前面的程序一樣,這個簡單的程序允許用戶輸入一個公基金代號并從WWW上的金融報價服務(wù)商那里取回報價。
kjava應(yīng)用程序被稱作 spotlet。 事實上,一個應(yīng)用程序可以由很多 spotlet組成,但是在任何時間只有一個 spotlet可以顯示在 Palm屏幕上。 在我們的例子中,我們創(chuàng)建一個基本 spotlet-- RequestFormSpotlet.java,為我們的兩個 spotlets子類提供用戶界面。代碼段 2擴展了基本的 RequestFormSpotlet以便得到并儲存一個報價。 RetrieveSpotlet也擴展了基本 RequestFormSpotlet并允許儲存的報價被取回(見圖)
代碼段2
import com.sun.kjava.*;
public final class FundSpotlet extends RequestFormSpotlet {
public static void main (String args[]) {
new FundSpotlet().draw();
}
private void draw() {
initForm();
setTitle("Fund Quote Requested");
}
public void penDown(int x, int y){
if (getExitButton().pressed(x,y)){
getGraphic().playSound(Graphics.SOUND_CONFIRMATION);
System.exit(0);
}
if (getSymField().pressed(x,y))
getSymField().setFocus();
if (getGetButton().pressed(x,y)) {
quoteRequested();
}
}
private void storeQuote (String fund, String newQuote) {
int dbType = 0x46554e44;
int dbCreator = 0x43415454;
com.sun.kjava.Database quoteDB;
try {
quoteDB = new com.sun.kjava.Database(dbType,
dbCreator, com.sun.kjava.Database.READWRITE);
if (!quoteDB .isOpen()) {
com.sun.kjava.Database.create(0, "MutualFundQuotes",
dbCreator, dbType, false);
quoteDB = new com.sun.kjava.Database(dbType,
dbCreator, com.sun.kjava.Database.READWRITE);
}
byte[] data = (fund + "#" + newQuote).getBytes();
quoteDB.addRecord(data);
quoteDB.close();
}
catch (Exception recordException) {
System.out.println("Unable to store quote and/or use
Mutual Fund Quote database.");
}
}
private void getAndDisplayQuote() {
String fundSymbol = getSymField().getText();
if (fundSymbol.length() > 0) {
String theQuote = QuoteService.getQuote(fundSymbol);
if (theQuote != null) {
storeQuote(fundSymbol, theQuote);
message(theQuote);
}
else
message("No quote. Check Symbol");
}
}
private void quoteRequested() {
message("");
getGraphic().playSound(Graphics.SOUND_STARTUP);
if ((getSymField().getText().length() > 0)) {
getAndDisplayQuote();
} else
{
message("Symbol required!");
}
}
}
在 RequestFormSpotlet程序中,類似于 MIDP中的 Display對象,單獨的 Graphics管理許多 spotlet用戶界面顯示。它考慮到了屏幕會被清除,顯示邊界會被建立。 不象 MIDlet,沒有屏幕或畫布對象來讓我們添加用戶界面小組件, 取而代之的是按鈕、文本字段等等,直接描畫在 spotlet上。 paint()方法利用圖形環(huán)境從的 Graphics在屏幕上顯示小組件。
我們的MIDP程序的 QuoteService類的大部分可以重新使用。 因為 kjava沒有象 MIDP中HttpConnection這樣特定的連接器界面,所以我們必須利用更多標(biāo)準的一般的連接器結(jié)構(gòu)表單獲取 HTTP鏈接。 為了做到這一點,使用代碼段 3中的代碼替換 getQuotePage()方法。注意注意使用 Connector,就像在 MIDP中我們使用 HttpConnection一樣。
代碼段3
private static String getQuotePage(String symbolString) {
StringBuffer quotePage = new StringBuffer();
int ch;
try {
InputStream in = Connector.openInputStream (
"testhttp://someurl/some_application?page=++&mode=fund&symbol="+
symbolString);
while ((ch = in.read()) > 0) {
quotePage.append((char)ch);
}
in.close();
return quotePage.toString();
} catch (IOException ex) {
System.out.println("Exception reading quote from
HTTP Connection");
return null;
}
}
Palm設(shè)備廣泛利用數(shù)據(jù)庫, 你的 Palm中的通訊簿、備忘錄和記事本應(yīng)用程序都與數(shù)據(jù)庫有關(guān)。 kjava程序包提供了一個非常小的 Database類,不僅可以創(chuàng)建并保持應(yīng)用程序數(shù)據(jù),而且可以訪問現(xiàn)有的數(shù)據(jù)庫。 如果你熟悉 Palm數(shù)據(jù)庫,你可能會對 kjava Database類提供的功能和信息感到失望。 然而,請再次記住, kjava只是一個演示的版本。
在我們的例子中,我們的 spotlet訪問一個 Palm數(shù)據(jù)庫 (如果不存在的話,則創(chuàng)建一個新的數(shù)據(jù)庫)來儲存公基金報價。每個 Palm數(shù)據(jù)庫都必須有名字、創(chuàng)建者 ID (一個 Palm登記的的標(biāo)識號 ) 和一個指定到某個單獨應(yīng)用程序的類型號。 試圖打開數(shù)據(jù)庫要通過嘗試創(chuàng)建一個帶有 ID信息的數(shù)據(jù)庫實例來實現(xiàn)。 就象 MIDP RecordStore,記錄被添加進 kjava數(shù)據(jù)庫,通過把一個字節(jié)數(shù)組當(dāng)成記錄添加到數(shù)據(jù)庫中的形式。
五、J2ME規(guī)范
在 J2ME內(nèi)還有很多子規(guī)范, J2ME的重要的部分如下:PersonalJava、K虛擬機 (KVM)、Java嵌入服務(wù)器以及 PersonalJava的兩個擴展規(guī)范: JavaPhone和 JavaTV應(yīng)用程序接口。 你可以想象, JavaPhone是一個定位于無線電智能電話和互聯(lián)網(wǎng)絡(luò)可視電話的應(yīng)用程序接口,而 JavaTV則滿足機頂盒市場的需求。
下面我想詳細的談一談以上的規(guī)范:
1、PersonalJava
PersonalJava應(yīng)用程序環(huán)境目標(biāo)是 Web連接消費設(shè)備----常常執(zhí)行來自網(wǎng)絡(luò)的小應(yīng)用程序。問題是 PersonalJava如何適合 J2ME的配置和簡表方案。 答案是 PersonalJava將被包容進 Connected Device Configuration中,終將被定義為 Personal簡表,即前面所談到的Personal簡表。
另一方面,有一段時間將有兩個 Java應(yīng)用程序接口為嵌入開發(fā)世界服務(wù): PersonalJava和 EmbeddedJava。 PersonalJava偎依在 J2ME大傘之下, 可為什么 EmbeddedJava不呢? EmbeddedJava不和 PersonalJava同在 J2ME內(nèi),是因為在 PersonalJava和 EmbeddedJava應(yīng)用程序之間有一個基本的差別。 PersonalJava應(yīng)用程序期望連接到某類網(wǎng)絡(luò)中下載并執(zhí)行小應(yīng)用程序。 按照這種觀點, PersonalJava設(shè)備就是一般用途的消費設(shè)備; 它們的能力可以被擴展。
相比之下, EmbeddedJava設(shè)備則慘了點。 它們執(zhí)行的功能都非常具體的,基本沒有必要提供下載新的代碼到 EmbeddedJava設(shè)備的能力。 Hence, PersonalJava設(shè)備使用可擴展 Java應(yīng)用程序接口; 而EmbeddedJava設(shè)備則沒有,因為沒有必要使用。
PersonalJava可以以兩種形式得到: 由原碼形式的,提供給那些對把PersonalJava移植到其他設(shè)備感興趣的開發(fā)者,那些已經(jīng)把 PersonalJava移植到某個具體的操作系統(tǒng)和處理機的組織提供二進制形式的 PersonalJava環(huán)境。有興趣探索 PersonalJava的開發(fā)者如果沒有二進制平臺也可以使用 PersonalJava模擬環(huán)境 ( PJEE )。 這個模擬器運行于 Solaris/SPARC或 Windows,并且在許多配置中可用。 這些多種多樣的配置基于“ look and feel”和類庫支持 (環(huán)境是否提供 PersonalJava規(guī)范中規(guī)定的限度的或的類庫)。PJEE包括類文件,一個應(yīng)用程序 launcher和一個 appletviewer (兩者都是為了調(diào)試功能并使其化)和其它的附帶的文件 (例如字體敘述文件)。
J2ME家族的另一位成員 JavaCheck實用程序,提供了 PersonalJava的補充支持。 你把應(yīng)用程序傳過 JavaCheck,它將告訴你你的應(yīng)用程序在一個 PersonalJava環(huán)境中能否順利地執(zhí)行。 JavaCheck檢查類之間的依賴關(guān)系,如果應(yīng)用程序調(diào)用了一個在 PersonalJava不可用的應(yīng)用程序接口,它就會給出一個警報信號。 (據(jù)我所知,目前有兩種JavaCheck的版本可用,一個是用于檢驗 PersonalJava 1.0版應(yīng)用程序,另一個用于檢驗 1.1.x版程序。 當(dāng)前的 PersonalJava應(yīng)用程序接口規(guī)范是 1.2,用于這一版本的 JavaCheck還沒有。 讀者請去Sun相關(guān)網(wǎng)站去看看( http : file://java.sun.com/products/personaljava)。
2、KVM
前面我也說過,KVM是用于 J2ME平臺小的虛擬機,并且是用于CLDC配置的虛擬機。可是J2ME應(yīng)用程序并不一定非要使用 KVM,J2ME技術(shù)可以使用任何虛擬機,不過至少應(yīng)當(dāng)有 KVM這樣的功能。
為了滿足基于KVM的設(shè)備一般只有狹小的內(nèi)存空間和有限的處理能力的事實, KVM使用 C編寫 (它不是現(xiàn)有的VM改進了的以后的產(chǎn)品)。 此外, KVM是模塊化的, 也就是說,它是由模塊構(gòu)建的,當(dāng)某個模塊實現(xiàn)了預(yù)先設(shè)定的目標(biāo)后,就可以很容易地把這一模塊卸載。 可選的某塊包括: 大的數(shù)據(jù)類型 ( long、 float和 double ),多維數(shù)組、類文件驗證等。
KVM的本地界面以輕便性為原則構(gòu)建,所以在KVM中任務(wù)切換不依賴硬件產(chǎn)生的記時器中斷,因此在這種意思上來說不是搶先式。任務(wù)切換發(fā)生在虛擬機執(zhí)行了一個預(yù)設(shè)編號的字節(jié)碼之后。 并且, KVM的無用單元收集利用一個標(biāo)記清掃(mark and sweep)算法來實現(xiàn)無用單元釋放。 因此,對象引用是直接的,就像標(biāo)準 Java一樣。
當(dāng)然,除了虛擬機以外還有許多可用的執(zhí)行環(huán)境,在小型設(shè)備中,虛擬機必須要么被擴展,要么在附加工具協(xié)助下提供一個更加完整的運行期環(huán)境,正是這個原因, KVM需要附帶的工具,比如說, JavaCodeCompact工具提供了預(yù)鏈接和預(yù)加載類, 允許Java類被直接地鏈接進虛擬機中。((設(shè)備上所有的應(yīng)用程序使用的類 can直接地嵌入虛擬機。)
KVM一個可選的附件就是 Java Application Manager ( Java應(yīng)用程序管理器,簡稱 JAM )。JAM的工作就是處理下載、安裝、執(zhí)行和卸載 CLDC設(shè)備上的應(yīng)用程序的細節(jié)問題,因為資源有限,在CLDC設(shè)備上有可能不存在這些功能。JAM也處理更新安裝應(yīng)用程序的操作。(如果更新過程失敗,它甚至可以重新使用舊的應(yīng)用程序。 )
3、Java Embedded Server(Java嵌入服務(wù)器)
Java Embedded Server( Java嵌入服務(wù)器,簡稱 JES),在 PersonalJava基礎(chǔ)上建立,是一個用于嵌入式網(wǎng)絡(luò)設(shè)備的運行期環(huán)境。為了理解 JES,你必須理解兩個核心概念:服務(wù)和服務(wù)空間結(jié)構(gòu)。后者是前者的容器。服務(wù)程序是運行于一個 JES服務(wù)器上的組件化程序;服務(wù)空間結(jié)構(gòu)是為服務(wù)程序提供生命周期 支持的環(huán)境。
技術(shù)上說,服務(wù)程序是界面的實現(xiàn),事實上,它是一個實現(xiàn)特定活動的Java類集合。比如說,假如把 JES配置為一個家庭的氣候控制系統(tǒng)的服務(wù)器,可以把從模數(shù)轉(zhuǎn)換器讀到的溫度數(shù)據(jù)放進一個數(shù)據(jù)組件程序中。我就可以稱這個組件為ReadThermostats服務(wù)程序。
在 JES的領(lǐng)域,服務(wù)的封裝媒介稱為 bundle。簡單地說,bundle就是一個帶有特殊內(nèi)容的JAR文件。服務(wù)程序和bundle之間有一對一關(guān)系,一個bundle帶有一個服務(wù)程序。服務(wù)程序和 bundle之間有一對一關(guān)系,一個 bundle帶有一個服務(wù)程序。可這也不一定,一個 bundle可以設(shè)置多個服務(wù)程序索引 (注意, JES提供的所有的核心服務(wù),每個 bundle中只有一個 )。
正如前面提到的那樣,服務(wù)空間的一項工作就是管理服務(wù)程序的生命周期,這個工作的很大的部分包括解決服務(wù)隸屬關(guān)系。bundle內(nèi)容的一個重要的部分是bundle服務(wù)的依賴信息。所以,當(dāng)服務(wù)空間打開一個bundle安裝它的服務(wù)時,服務(wù)空間就可以確定外部需要什么服務(wù)。而且,一個服務(wù)的依賴關(guān)系并不是靜止不變的,它們可以隨某些事件改變。比如說當(dāng)服務(wù)程序更新時的變化就是一個很好的例子。一個服務(wù)的新的版本可以添加或去除依賴關(guān)系。服務(wù)空間跟蹤并解決這樣的動態(tài)依賴關(guān)系。如果服務(wù)空間處理所有服務(wù)程序的生命周期,這就暗示了服務(wù)空間被賦予知曉一切的能力,那就是說,它能夠推論結(jié)構(gòu)、依賴、安裝的細微差別等所有它負責(zé)的服務(wù)。服務(wù)空間通過在 bundle內(nèi)伴隨服務(wù)的 Java代碼模塊處理一些任務(wù),這些模塊被稱作 wizard(向?qū)ВES向?qū)歉鶕?jù)它們完成的任務(wù)命名的:
Dependencies -向?qū)Ц嬖V調(diào)用者一個bundle依賴關(guān)系是什么。
Installer-向?qū)幚韇undle中服務(wù)的安裝和刪除操作。
Activator -向?qū)е廊绾螁雍徒K止服務(wù)。
Updater -向?qū)Э丶耣undle中的服務(wù)。(更新向?qū)Р粌H知道更新一個服務(wù),而且知道在何時和什么情況下更新服務(wù)。 )
About -這個向?qū)В拖袼Q意味的那樣,返回關(guān)于 bundle內(nèi)容的信息。
Dispatcher -這是一種元向?qū)В╩eta-wizard)。服務(wù)空間調(diào)用dispatcher向?qū)Фㄎ灰粋€bundle的其他向?qū)А?
當(dāng)一個 JES服務(wù)器啟動的時候,服務(wù)空間并不是完全沒有啟動服務(wù)。JES定義一組核心服務(wù)(可選),這些都是任何 JES服務(wù)器的組成部分。這些核心服務(wù)包含:
HTTP服務(wù)
日志 -記錄錯誤和事件日志
日期 -精確到秒的日期/時間服務(wù)
連接管理器 -提供網(wǎng)絡(luò)服務(wù)和Socket綁定,也處理連接接收。
線程管理器 -管理服務(wù)器提供的線程。thread管理器支持線程池并允許有效使用線程上界的規(guī)范。
計劃程序 -提供未來的事件計劃安排 (可用于告訴服務(wù)器某某動作必須在某某事件發(fā)生 )
RMI
SNMP
控制臺 -提供遠程管理服務(wù)器功能
基于 HTTP的遠程應(yīng)用程序接口實現(xiàn)
基于 RMI的遠程應(yīng)用程序接口實現(xiàn)
如果你把服務(wù)空間結(jié)構(gòu)當(dāng)成 JavaBean中的容器的話, JES就變得容易理解了。在這種類比關(guān)系中,服務(wù)程序就相當(dāng) JavaBean。那么,正象組件容器提供一個環(huán)境供 JavaBeans實例化、運行一樣,服務(wù)空間就是以實例化的服務(wù)的聚集地。服務(wù)空間管理安裝、實例化、執(zhí)行、終止以及卸載服務(wù);它也提供應(yīng)用程序接口供服務(wù)交互作用。