CLDC的目的
CLDC的范圍
CLDC不包括的范圍(即由MIDP解決的)
CLDC的安全性
低端的基于虛擬機(jī)的安全性由下載時(shí)對(duì)class文件的審核(verification)步驟來(lái)保證。(如果你寫(xiě)過(guò)并編譯過(guò)MIDlet程序,就會(huì)知道這一步是必須的。這里有一個(gè)概念就行了,我會(huì)在后面講述如何創(chuàng)建MIDlet程序時(shí),詳細(xì)介紹具體的步驟)?;趹?yīng)用程序的安全性通過(guò)使每個(gè)應(yīng)用程序分別運(yùn)行在相對(duì)獨(dú)立的封閉環(huán)境中來(lái)保證并且處于被保護(hù)的系統(tǒng)package中的類不能被應(yīng)用程序重載(overridded)。
對(duì)于Java語(yǔ)言支持的特殊方面
CLDC總的來(lái)說(shuō)是與Java語(yǔ)言完全兼容的,但需注意以下幾點(diǎn):
不支持浮點(diǎn)數(shù)據(jù)類型(即沒(méi)有float和double)(這實(shí)際上主要是由于CLDC所面向的設(shè)備,其硬件因其內(nèi)存限制或是基于安全性的考慮不支持浮點(diǎn)運(yùn)算)
不支持類實(shí)例(class instance)的終結(jié)(finalization),即不存Object.finalize()方法。(注:finalization指的是java中提供的有別與garbage collection的另外的一種對(duì)象清理方法。具體可參看侯捷老師譯的Bruce Eckel的《Thinking in Java 第二版》,可以在www.jjhou.com中下載)
有限的錯(cuò)誤處理,即大部分Java.lang.Error的子類都未被支持。與此相反,CLDC包括了相當(dāng)完備的異常(exception)類。
對(duì)于Java虛擬機(jī)(Java Virtual Machine)支持的特殊的方面
實(shí)質(zhì)上CLDC在其嚴(yán)格的內(nèi)存限制下達(dá)到了對(duì)Java虛擬機(jī)相當(dāng)程度的兼容性。不過(guò)還是有下列不同點(diǎn):
類文件審核過(guò)程(classfiles Verification)
CLDC要求其下層的虛擬機(jī)能夠辨別并拒絕非法的class文件。但由于CLDC本身面向小內(nèi)存消耗的小型設(shè)備這一前提。其類文件檢測(cè)機(jī)制與J2SE中定義的標(biāo)準(zhǔn)類文件審核機(jī)制還有所不同。請(qǐng)注意看下圖:
請(qǐng)注意上圖所示CLDC中的預(yù)審核(preverification)過(guò)程。這是CLDC區(qū)別于通常的類文件審核過(guò)程的關(guān)鍵。如上圖所示,當(dāng)源程序被編譯后,必須被預(yù)審核器預(yù)審核,然后才能被下載到目標(biāo)設(shè)備上去。之所以有這一步驟,主要是為了減輕KVM中審核器的負(fù)擔(dān),加快審核速度。就像我前文提到的,這是出于對(duì)CLDC支持的硬件的考慮(畢竟手機(jī)和PDA并沒(méi)有我們PC機(jī)那樣奔騰的“芯”呀!^-^)。這里記住這個(gè)概念就行了。具體的操作方法我會(huì)在以后講述編寫(xiě)MIDlet程序時(shí)介紹。
如果不嚴(yán)格的說(shuō),CLDC的類庫(kù)是J2SE的一個(gè)小的子集,有以下這種近似關(guān)系成立,即J2SE包含CDC包含CLDC。但要注意CLDC并未完全包含于J2SE,它還包括一些專門針對(duì)無(wú)線設(shè)施的類。所以可以把CLDC的類庫(kù)簡(jiǎn)要?jiǎng)澐譃閮刹糠郑簭腏2SE繼承的類和CLDC專有的類。
1. 從J2SE繼承的類
這部分包括三個(gè)package,即java.lang,java.util和java.io。注意即使這些從J2SE繼承的的類,也是大大“縮了水”的。例如java.util的類與接口由J2SE的47個(gè)縮減到10個(gè)。另外兩個(gè)也有相應(yīng)縮減。
系統(tǒng)類
From java.lang:
Object, Class, Runtime, System, Thread, Runnable,
String, StringBuffer, Throwable
數(shù)據(jù)類型類
From java.lang:
Boolean, Byte, Short, Integer, Long, Character
容器類(container class)
From java.util:
Vector, Stack, Hashtable, Enumeration
I/O 類
From java.io:
InputStream, OutputStream, ByteArrayInputStream,
ByteArrayOutputStream, DataInput, DataOutput,
DataInputStream, DataOutputStream, Reader, Writer,
InputStreamReader, OutputStreamWriter, PrintStream
日期與時(shí)間類
From java.util:
Calendar, Date, TimeZone
附加的實(shí)用類
java.util.Random, java.lang.Math
異常類(Exception Classes)
From java.lang:
Exception, ClassNotFoundException,
IllegalAccessException, InstantiationException,
InterruptedException, RuntimeException,
ArithmeticException, ArrayStoreException,
ClassCastException, IllegalArgumentException,
IllegalThreadStateException, NumberFormatException,
IllegalMonitorStateException, IndexOutOfBoundsException,
ArrayIndexOutOfBoundsException,
StringIndexOutOfBoundsException,
NegativeArraySizeException, NullPointerException,
SecurityException
From java.util:
EmptyStackException, NoSuchElementException
From java.io:
EOFException, IOException, InterruptedException,
UnsupportedEncodingException, UTFDataFormatException
錯(cuò)誤類
From java.lang:
Error, VirtualMachineError, OutOfMemoryError
2. CLDC專有的類
這里sun提供了javax.microedition.io包。用它來(lái)提供與外界溝通的橋梁。(注:就像在J2SE中我們利用java.net.*)注意,所有的連接都由javax.microedition.Connector創(chuàng)建。例如:
你可以打開(kāi)一個(gè)http連接通過(guò)Connector.open("http://www.chinajavaworld.com")
javax.microedition.io的接口包括:
Connection, InputConnection, OutputConnection,
StreamConnection, ContentConnection, DatagramConnection,
StreamConnectionNotifier
這里再說(shuō)明一點(diǎn),實(shí)際上你也可以看出,CLDC所包括的類庫(kù),并不足以開(kāi)發(fā)應(yīng)用程序。例如,沒(méi)有UI界面的支持等。這也正是CLDC的設(shè)計(jì)理念。CLDC本身就從未想過(guò)要解決所有的問(wèn)題。這些問(wèn)題要靠其上層的Profile-MIDP來(lái)解決。例如javax.microedition.lcdui就是定義在MIDP中的UI包。
由于MID這類設(shè)備,在屏幕、內(nèi)存、處理器等問(wèn)題上有諸多限制,在手機(jī)或是PDA等MID上開(kāi)發(fā)應(yīng)用程序必須要考慮一些技術(shù)上的特殊點(diǎn)。
下面給出一些MID設(shè)備的特性:
還有很多軟件上的特性,如讀寫(xiě)non-volatile內(nèi)存(就是掉電后不會(huì)失去內(nèi)容的內(nèi)存,如flash)。讀寫(xiě)無(wú)線設(shè)備接口的API,等等。除了上訴技術(shù)上的問(wèn)題,你還得注意你的程序要簡(jiǎn)單易用且穩(wěn)定可靠。尤其是可靠性,你開(kāi)發(fā)的是通訊設(shè)備,用戶是不能忍受程序有什么紕漏而影響到通話的。你要牢記這一點(diǎn)。
如前文所述,sun在CLDC之上定義了MIDP(Mobile Information Device Pro-file)層,用以提供對(duì)UI、永久存儲(chǔ)介質(zhì)(persistinace storage)、和網(wǎng)絡(luò)等更高層的(相對(duì)于CLDC)支持。那么,讓我們來(lái)具體看看MIDP的類庫(kù)。
MIDP由四個(gè)javax.microedition包組成,它們包括:
注:如果在加上語(yǔ)言和實(shí)用類(java.lang和java.util)則有六個(gè)。
MIDPlet簡(jiǎn)介
MIDP中定義的應(yīng)用程序稱為MIDlet。任何一個(gè)MIDlet都是javax.microedition.midlet.MIDlet的子類,必須繼承自javax.microedition.midlet.MIDlet。這很顯而易見(jiàn)。我們?cè)贘2SE中編過(guò)Applet,Applet就必須繼承自java.applet.Applet。是不是很類似。請(qǐng)看下圖,說(shuō)明了MIDlet的繼承體系。
圖4 MIDlet的繼承體系
一個(gè)簡(jiǎn)單的MIDlet
//HelloWorld.java,一個(gè)最簡(jiǎn)單的MIDlet程序。 |
該程序顯示“HelloWorld”字符串。程序本身非常簡(jiǎn)單,如果你熟悉JavaApplet編程的話,你會(huì)發(fā)現(xiàn)與Applet很類似。好,我們先把它編譯,運(yùn)行一下看看。
編譯之前的準(zhǔn)備:
下載好后,先安裝JDK1.3,(具體關(guān)于安裝和設(shè)置我就不詳述了,想來(lái)大家都很清楚。如果您不清楚,請(qǐng)參考相應(yīng)資料。)在安裝J2ME Wireless Toolkit 1.0.3,它會(huì)自動(dòng)找到您的JDK1.3,并作相應(yīng)設(shè)置。如果您不用命令行的話,環(huán)境變量也不用設(shè)置直接可在圖形界面上運(yùn)行,非常方便。關(guān)于環(huán)境變量的設(shè)置請(qǐng)自己參考手冊(cè)。
編譯的步驟
如果你按上述已經(jīng)安裝好JDK和J2mewtk,請(qǐng)按以下步驟編譯,實(shí)際上是非常簡(jiǎn)單的:
(注:下述默任JDK安裝在c:\JDK1.3,J2ME Wirless Toolkit 安裝在c:\J2mewtk\)
1. 開(kāi)始->程序->J2ME Wirless ToolKit 1.0.3->KToolBar
2. 這時(shí)會(huì)出現(xiàn)"J2ME Wirless ToolKit"窗口,點(diǎn)"New project"按鍵,在Project name項(xiàng)填:HelloWorld;在MIDLet Class Name填:HelloWorld。點(diǎn)擊Creat project。
3. 這時(shí)會(huì)出現(xiàn)Setting for project對(duì)話窗,采取默認(rèn)即可。點(diǎn)擊ok。
這時(shí)請(qǐng)注意,因?yàn)闆](méi)有down sun的IDE,所以你要手工把你事先編輯好的HelloWorld.java放置在c:\j2mewtk\apps\HelloWorld\src\目錄下。這時(shí),按“Build”鍵,如果一切正常,將提示編譯完畢。這時(shí)在device下拉選單中選定你想要的設(shè)備,再按“run”鍵,終于大功告成。你可以多選幾個(gè)不同設(shè)備,感受一下,不錯(cuò)吧。
我們已經(jīng)成功編譯并運(yùn)行了一個(gè)簡(jiǎn)單的MIDlet程序?,F(xiàn)在,讓我們來(lái)分析一下MIDlet的結(jié)構(gòu),了解一下它的Lifecycle。
通過(guò)對(duì)源程序的觀察,我們可以發(fā)現(xiàn)MIDlet程序的運(yùn)行是由startApp(),pauseApp()和destroyApp()這3個(gè)方法控制的。它們?cè)趈avax.microedition.midlet
.MIDlet中定義。所有的MIDlet都必須有這3個(gè)方法。
顧名思義startApp()方法用于標(biāo)志一個(gè)MIDlet的開(kāi)始執(zhí)行。不過(guò)這里要注意一點(diǎn),與HelloWorld程序的constrctor不同。startApp()不光是在初始化完一個(gè)MIDlet時(shí)執(zhí)行,只要該MIDLet被從Paused態(tài)激活(變?yōu)锳ctive態(tài)),startApp()就會(huì)被調(diào)用。
pauseApp()方法標(biāo)志著MIDlet進(jìn)入Pause態(tài)。而destroyApp()方法標(biāo)志著MIDlet進(jìn)入destroyed態(tài)。(注意:這里嚴(yán)格的講應(yīng)該說(shuō)成:方法被調(diào)用并成功返回標(biāo)志著...)
看完上面的描述,大家可能會(huì)滿頭霧水,又是方法,又是狀態(tài)的,什么跟什么嗎?這還得從MIDlet的執(zhí)行機(jī)制講起。
MIDlet的執(zhí)行是通過(guò)Application Management software來(lái)管理的。這玩意兒是處在操作系統(tǒng)級(jí)別上來(lái)管理MIDlet運(yùn)行的底層機(jī)制的總稱,所謂MIDlet state(MIDlet狀態(tài))就是它一手操辦,控制管理的。MIDlet state確保了AMS隨時(shí)可以消滅該MIDlet,同時(shí)MIDlet也有辦法進(jìn)入一個(gè)Pause態(tài),并可再次激活。
MIDlet State 分為Paused,Active,destroyed三種。當(dāng)AMS創(chuàng)生一個(gè)新的MIDlet實(shí)體時(shí),對(duì)應(yīng)于MIDlet,表現(xiàn)為其constructor被調(diào)用,進(jìn)入Paused狀態(tài)。當(dāng)所有的準(zhǔn)備工作都做好后,AMS判斷現(xiàn)在MIDlet可以運(yùn)行了,于是調(diào)MIDlet.startApp()方法。進(jìn)入Active態(tài)。當(dāng)AMS決定要把MIDlet轉(zhuǎn)入Paused態(tài),就會(huì)調(diào)用MIDlet.pauseApp()方法,MIDlet就會(huì)暫停執(zhí)行,通常Paused態(tài)會(huì)用于釋放所占資源。當(dāng)AMS判斷MIDlet不再需要,就會(huì)調(diào)用MIDlet.destroyApp(),MIDlet被消滅。
請(qǐng)注意我上述是站在AMS的角度在談AMS如何控制MIDlet的狀態(tài)改變。程序員也可請(qǐng)求MIDlet的狀態(tài)的變換,通過(guò)調(diào)用resumeRequest, notifyPaused, notifyDestroyed這三個(gè)方法。
我們的HelloWorld程序先把destroyApp()的unconditional值置為false,拋出一個(gè)MIDletStateChangeException 異常,表示MIDlet這時(shí)還不想被destroy。notityDestroyed()通知AMSMIDlet進(jìn)入destroyed態(tài)。具體的細(xì)節(jié)請(qǐng)參閱MIDP API文檔。
下面給出一個(gè)MIDlet的最簡(jiǎn)單的狀態(tài)流程:
//FlowMIDlet.java MIDlet的最簡(jiǎn)單的狀態(tài)流程 |
MIDlet的狀態(tài)的改變可以用下圖表示:
這里還要說(shuō)幾句閑話,關(guān)于AMS,其作用不止是控制MIDlet的運(yùn)行狀態(tài)。它實(shí)際上際上負(fù)責(zé)了MIDlet的整個(gè)運(yùn)行機(jī)制。關(guān)于AMS進(jìn)一步的描述,請(qǐng)參見(jiàn)王森老師的文章-“利用Java撰寫(xiě)手機(jī)應(yīng)用-Java Application Manager篇”(《程序員》,12期,2001)。注意其中JAM就是AMS。
好了,J2ME(CLDC/MIDP)的簡(jiǎn)介就算是結(jié)束了。把帖子轉(zhuǎn)成html實(shí)在是一項(xiàng)很累的工作。試過(guò)這后我才明白這個(gè)道理。如果您看過(guò)之后,有那么一點(diǎn)幫助的話,那就算是對(duì)我最大的報(bào)償了。如果您覺(jué)得文章有什么錯(cuò)漏之處,或是有什么感想,歡迎給我E-mail。
聯(lián)系客服