low gui
Java-enabled 手機軟體設計考量
Software Design Considerations for Java-enabled Phones
摘要
在本篇論文中,我們將會描述關於移植Sun公司所定義的J2ME CLDC & MIDP到手機環境上時所需要注意的事項,其中包含系統需求、編譯器的需求、函式庫的需求、Java虛擬機器的移植、MIDP所定義的高階及低階使用者介面的移植、及相容性測試相關的主題,最後會介紹我們發展的一些成果及未來努力的方向。
關鍵詞
J2ME
(Java 2 Micro Edition)
CLDC
(Connected Limited Device Configuration)
MIDP
(Mobile Information Device Profile)
TCK
(Technology Compatibility Kit)
1. 前言
隨著手機技術的發展,單純的通話功能已經逐漸地無法滿足現代人的需求,3G時代即將來臨,多功能合一的手機將是未來發展的趨勢。隨著頻寬的增加,硬體的進步,手機將可動態下載許多應用程式。然而手機平台在傳統上是一個封閉的系統,有不同的作業系統,不同的硬體環境,這意味著程式設計者必須針對各個平台設計程式。而對使用者而言,如果需要為自己的手機添加新功能必須分辨自己的手機平台,這對一般使用者而言也是件很麻煩且容易出錯的事。於是可以跨平台的 Java不管是對工程師或是對使用者而言,便成了一個良好的解決方案。Sun公司特別為了這一類的平台制定了J2ME的規範,在J2ME的平台下,程式設計師只要透過Sun制定的MIDP應用程式設計介面來撰寫手機的程式便可以達到跨平台的目的,然而這一切的功能都有賴於底層Java 虛擬機器的幫忙。由於Java乃是採用直譯器的方式來執行,加上手機的硬體環境不比PC,所以在速度上就變成了一個重要的課題。本文將針對J2ME MIDP在手機環境上的移植來作探討。
2. 系統需求
將Java移植至手機平台上,對於開發環境、編譯器、函式庫,有一些基本的需求,分別敘述如下。
2.1 編譯器
J2ME CLDC/MIDP包含了C及Java的原始碼。C的部分包含了虛擬機器的主體以及CLDC/MIDP內部的原生函式(native methods);Java的部分則包含了CLDC/MIDP函式庫的實作。
由於CLDC/MIDP內的C程式碼都是以符合ANSI C的標準寫成,編譯器只要能夠支援ANSI C的標準,所有的程式碼大致上都可以順利完成編譯。
C編譯器必須支援如表2.1.1所示的基本型別。
型別 描述
char 8位元的數值。可以是有正負號或無正負號。
signed char 有正負號的8位元的數值。
unsigned char 無正負號的8位元的數值。
short 有正負號的16位元的數值。
unsigned short 無正負號的16位元的數值。
int 有正負號的數值。可為16或32位元。
unsigned int 無正負號的數值。可為16或32位元。
long 有正負號的32位元的數值。
unsigned long 無正負號的32位元的數值。
void * 32位元的指標。
表2.1.1 基本型別
根據CLDC/MIDP的規範,浮點數的支援並不包含在內,因為CLDC/MIDP的目標平台是低階的硬體平台,如手機、呼叫器、PDA,其中所使用的微處理未必能夠勝任浮點數的運算。但如果硬體平台可以配合,亦可以將浮點數的支援加進來,這個時候C編譯器必須支援如表2.1.2所示的浮點數型別。
型別 描述
float 32位元的浮點數值。
double 64位元的浮點數值。
表2.1.2 浮點數型別
在實作上,可能會碰到特殊的情況。例如有些C程式的寫法,雖然並不明定於ANSI規範,但若編譯器不支援這樣的用法,便無法順利進行編譯。CLDC裡有一個工具叫做JCC,可以把CLDC/MIDP裡的Java程式庫轉換成C的形式,方便將這些程式和KVM加以連結成為單一個執行檔,可以節省動態分析 Java程式庫的時間,也方便將此單一執行檔整合進內嵌系統內。而JCC針對CLDC/MIDP之Java程式庫產生出來的C程式碼大約有12萬行。在這樣的情況下,若編譯器無法編譯由JCC自動產生出來的C程式,要去修改該程式使之可以順利完成編譯,便得花費一番心思。大部分的編譯器並不會有這種情況發生,但在我們的案例裡,確實遇到了這樣的情形。
Java部分的原始碼須以JDK 1.3加以編譯,並不會遇到相容性的問題。
2.2 函式庫
目標平台必須支援下列函式,否則必須自行實作相同功能的函式,或修改KVM來配合目標平台上現有之函式。
2.2.1 C語言函式庫
KVM會使用到下列函式:
□ 字串處理函式:strcat, strchr, strcmp, strcpy, strncpy, strlen
□ 記憶體搬移函式:memcpy, memmove, memset, memcmp
□ 文字輸出及格式處理函式:atoi, sprintf, fprintf, putchar
□ 例外處理函式:setjmp, longjmp
□ 記憶體配置函式:malloc, free, mmap, munmap, mprotect
□ 時間函式:time, gettimeofday, localtime
□ 信號處理函式:signal
□ 其他:abort
如果目標平台不支援其中的函式,可以自行實作功能相同的函式,或修改KVM來配合目標平台上現有之函式。
2.2.2 網路函式庫
J2ME CLDC支援網路傳輸的功能,會使用到下列的網路函式:
□ socket – 開啟連線用的socket
□ close – 關閉連線用的socket
□ bind – 建立socket與連線位址及連接埠之間的連結
□ connect – 建立連線
□ listen – 傾聽是否有連線的要求
□ accept – 接受連線
□ setsockopt – 設定socket選項
□ fcntl - 將連線設為non-blocking時使用
□ ioctl - 用來取得將會接收多少長度的資料
□ getsockname – 取得socket名稱
□ gethostbyaddr, gethostbyname , gethostbyname_r – 取得網路位址
□ send, sendto – 傳送訊息
□ recv, recvfrom – 接收訊息
□ htons, htonl – 進行主機端與網路端之間的數值順序轉換
如果目標平台不支援其中的函式,可自行實作功能相同的函式,或修改KVM來配合目標平台上現有之函式。
3. 移植爪哇虛擬機器
基本上,KVM本身設計為portable,所有的程式碼皆符合ANSI C的標準。因此單純就KVM本身而言,針對移植所必須進行的修改並不多。另外,可視情況修改KVM內部之下列函式:
□ AlterUser – 提示使用者,系統發生了嚴重的錯誤
□ allocateHeap – 配置heap區塊,其位址必須為4的倍數
□ freeHeap –釋放使用allocateHeap所配置的區塊
□ InitializeVM – 啟始化虛擬機器
□ FinalizeVM – 在關閉虛擬機器之前進行清理的工作
□ InitializeNativeCode – 啟始化native程式碼
□ FinalizeNativeCode – 在關閉虛擬機器之前進行native程式碼相關的清理工作
□ InitializeClassLoading – 初始化class載入器
□ FinalizeClassLoading - 在關閉虛擬機器之前進行class載入器相關的清理工作
如果希望在目標平台上加入非同步原生函式的支援,則必須實作下列函式:
□ yield_md – 暫時停止目前的執行緒,讓其他的執行緒優先執行
□ CallAsynchronousFunction_md – 呼叫指定的函式,以thread ID作為參數
□ enterSystemCriticalSection – 進入critical section
□ exitSystemCriticalSection – 離開critical section
4. 移植圖形式人機介面
在SUN的MIDP參考實作中,將行動式設備所使用的圖形式人機介面的應用程式介面(Graphical User Interface API)設計成兩個部分:High-level GUI和Low-level GUI。High-level GUI的部分主要包含了一組視窗元件(widgets),完全以Java實作,應用程式可以使用這些規格化的元件迅速建構應用程式,並且可以享有高度的跨平台特性。而Low-level GUI則包含了以Java實作的部分及以C語言實作的部分(native code),應用程式可以使用這些API直接繪製低階圖形,例如直線、弧線、點矩陣圖形及文字等,並且可以自行定義事件的處理方式,例如觸摸式面板的支援,應用程式也可以使用這些API自行製作其他的圖形元件(customized widgets),或是使用這些API來提昇程式執行的繪圖效率。
以Java類別來分類,可以劃分出高階與低階所包含的API,大致如表4.0.1及表4.0.2所述。
Display.java AlertType.java Command.java
CommandListener.java Displayable.java Canvas.java
Graphics.java Font.java Image.java
表4.0.1 在Low-level Graphics API中的類別
Screen.java Ticker.java Choice.java Alert.java
List.java TextBox.java Form.java Item.java
ChoiceGroup.java DateField.java Gauge.java TextField.java
ImageItem.java StringItem.java ItemStateListener.java
表4.0.2在High-level Graphics API中的類別
4.1 低階圖形式人機介面的移植
在J2ME的架構中,由於Java程式無法直接存取系統資源同時也維持Java本身的跨平台特性,因此在參考實作中Java系統類別庫會透過呼叫原生函式來存取系統資源。因此在移植MIDP到不同的目標平台時,移植相關的原生函式實作到目標平台成為首要的課題之一。
MIDP參考實作將與繪圖相關的原生函式定義在Graphics.java中,例如:drawLine、drawArc、drawString、 drawImage等;在Font.java中定義了應用程式使用字型的操作介面,並透過原生函式取得系統字庫中每個字元的寬度,來計算擺置在顯示幕上的位置;而目標平台的顯示幕特性(例如長、寬及支援色階)可以透過定義在Display.java中的DeviceCaps類別呼叫init原生函式來取得;此外,參考實作中為了讓系統相關的實作(指不同平台上因為軟硬體特性或是GUI設計需求而有所不同的部分)與標準Java類別庫實作分隔,使移植的工作得以模組化,在設計上使用Helper classes(com.sun.midp.ludui.*)來連接標準API(javax.microedition.lcdui.*)與目標平台的系統函式庫。
在參考實作1.0.2版本中,com.sun.midp.lcdui.DefaultEventHandler這個Helper class實作了事件處理的種類與接收的方式,並配合com.sun.midp.lcdui. DefaultInputMethodHandler這個Helper class來處理及顯示選單。移植時可以根據硬體特性來修改DefaultEventHandler中處理的事件種類,例如是否支援觸摸式顯示幕等。而為使目標平台上使用者介面的觀感(look-and-feel)一致,可以重新實作DefaultInputMethodHandler中定義的輸入介面及選單(soft-menu)的操作方法。
而Helper classes所呼叫的原生函式定義在defaultLCDUI.c之中,這些原生函式負責從Java虛擬機器中取出參數,然後呼叫定義在 nativeGUI.c、graphics.c、images.c及text.c中的函式,這些函式負責與系統平台所提供的繪圖機制連接。在 defaultLCDUI.c當中的函式不需要修改。而在nativeGUI.c定義了GetNextKVMEvent(),這個函式負責接收系統平台所傳遞而來的鍵盤等事件,在4.3節將詳述MIDP與KVM的事件處理模型。
其他還有一些原生函式所需要的相關函式定義在menus.c、events.c、imageDecode.c及pngDecode.c,這些函式在設計上與平台差異性無關,基本上並不需要修改。
4.2高階圖形式人機介面的移植
在參考實作中高階圖形式人機介面是以Java程式撰寫而成,具有可移植的特性。然而在產品化的過程中為了讓產品的圖形式人機介面具有一致性,需要重新實作視窗元件(widgets)及定義操作方法,讓觀感(look-and-feel)及操作方式保持一致。以下是修改實作方法的步驟:
1. 將需要修改的元件之原始碼(例如Srcreen.java或TextField.java)刪除大部份的程式,只留下public方法。
2. 加上屬性為package-private之showNotify及hideNotify原生函式(因為若使用系統平台所提供之視窗元件,則無法使用現有的notify方法,例如在Screen.java中所定義的)。
native void showNotify();
native void hideNotify();
依據不同視窗系統的設計理念,有時將需要在Java程式中實作paint方法。
void paint(Graphics g);
3. 為了與視窗系統溝通,必須加入適當的原生函式在Java程式與視窗系統間來傳遞資料。
4. 實作其他的public方法,維持API及與其他元件溝通的完整性。
5. 實作原生函式來與平台之視窗系統溝通。
4.3 事件處理模型
KVM的事件處理是以輪詢(polling)的方式來完成,並配合Java執行緒的排程機制,使得以Java執行緒實作的事件處理者(Event Handler)可以讀取到系統觸發的鍵盤等事件。
MIDP參考實作提供了一個可供具有小型顯示幕及單手鍵盤(one-handed keyboard)設備使用的事件處理者(DefaultEventHandler.java),可處理四種事件:KEY_EVENT、 PEN_EVENT、COMMAND_EVENT及TIMER_EVENT。DefaultEventHandler會新增一條Java執行緒,透過 events協定(延伸自Generic Connection Framework的架構)來讀取底層系統軟體所接收到的鍵盤及timer等事件。當EventHandler接收到事件時,會將事件依據種類分配給登錄的物件。
由於KVM為了提高可移植性,並沒有採用以接收中斷的方式來讀取事件,而在執行過程中以輪詢的方式來達成,那麼系統的鍵盤等事件何時會被讀進KVM之中呢?當KVM在重新切換執行緒之前,會讀取事件內容進入KVM的事件暫存器,然後切換至事件處理者執行緒,便會從KVM的事件暫存器讀取事件內容至 Java事件處理者中;若是KVM沒有讀取到事件便會將事件處理者執行緒暫停(suspend),直到KVM讀取到新的事件時,再將事件處理者執行緒喚醒並切換至該執行緒讀取事件內容,這樣可以降低因為頻繁地切換Java執行緒所帶來的額外負擔。
由於KVM採取在執行時期以輪詢的方式來接收事件,因此接收的次數與時機便成為影響整體執行效能及事件反應速度的重大因素,必須依照不同的作業系統架構及硬體速度來修改接收事件的方法,並調整輪詢的頻率。
此外,為了兼顧應用程式在動畫顯示上的表現,應用程式可以控制每次重畫(repaint)的間隔時間,而KVM使用timer來實作時必須盡量符合其反應時間。
5. 其他重要模組的設計與移植
MIDP是設計給行動式通訊產品所使用的軟體平台,除了圖形式人機介面之外,還包括網路通訊等相關模組,必須依據系統平台所提供之相關機制作適當修改或重新實作。可分為三個部份:
1. 應用程式管理軟體(MIDlet Management Software)
Java平台在通訊產品的應用最大的優點之一便是可動態下載及更新應用程式,而這需要配合儲存機制儲存下載的應用程式,及具有彈性的管理策略來相互合作。這些Java程式主要包含了com.sun.midp.Main、com.sun.midp.midlet.*及com.sun.midp. midletsuite.*(管理MIDlet的機制又稱為Java Application Manager)。產品化的過程中可以依據使用者介面的設計而與微瀏覽器結合,讓使用介面更具一致性。
2. 記錄管理系統(RMS,Record Management System)
為了讓MIDlet可以在執行時儲存動態的資料,因此MIDP規格裡亦制定了一套記錄管理系統,移植時若目標平台提供使用ANSI C規格的C函式庫來存取儲存設備,則不需再作修改,否則依據系統所提供的儲存機制需重新實作原生函式(修改定義在storage.c中的相關函式)。
3. 網路通訊支援(Networking Support)
在CLDC規格中制定了一套存取資料串流的軟體架構—Generic Connection Framework,而MIDP依循此架構並實作了部分的HTTP 1.1協定,用以當作應用軟體的標準網路通訊介面。由於HTTP協定是高階的通訊協定,可以使用IP協定或非IP協定來實作,在多樣化的行動通訊網路架構中,這樣的考量有助於Java行動通訊平台的推廣。在參考實作中,HTTP協定使用Java程式實作,具有可移植性,而相關的原生函式以socket函式庫來實作(定義在network.c及networkPrim.c中)。
6. 相容性測試
相容性測試為確保產品特性能符合某種規格,對Java的相關應用技術來說,為了確定所實作的產品能與規格相符,則必須透過TCK的驗證。至於什麼是TCK 呢?在了解什麼是TCK之前,我們必須先知道什麼是JCP。JCP為Java Community Process的縮寫,為制定Java相關規格的程序,依據目前JCP版本的定義,當某項規格在經過一連串的制定過程時,相關的RI及TCK皆必須在整個規格完成前被發展與實作。其中RI為Reference Implementation的縮寫,為規格實作的參考版本,例如我們所熟知的KVM即為CLDC的RI。至於TCK為Technology Compatibility Kit的縮寫,為制定規格的Spec Lead與Expert Group所發展的測試環境,其中包含了相關的測試、工具與文件。由於目前Java在各個領域的應用日趨廣泛,我們在此並不探討每種規格的TCK介面,僅針對MIDP TCK的Server與Client相關介面加以介紹。
6.1 MIDP TCK架構
MIDP TCK與Java 2 Platform, Micro Edition兩者間資料傳送的架構如圖6.1.1所示。在PC/Workstation端執行的程式為JavaTest,而在MIDP RI Platform端則為KVM。由圖中我們可瞭解到,PC/Workstation端與MIDP RI Platform間的資料傳送是透過Server、Client與Java Application Manager的協商。
圖6.1.1 MIDP TCK與Java 2 Platform,Micro Edition架構
當JavaTest啟動時,會透過Server接收來自Java Application Manager與Client的要求,而依據要求內容傳送新的測試程式至Client或Java Application Manager,或者接收來自於Client或Java Application Manager的測試結果。當我們啟動KVM時,必須啟動Java Application Manager,透過Java Application Manager向Server端要求新的測試程式並執行,而JavaTest會將新的測試程式、MIDPAgent與Client傳送至Java Application Manager,之後便可透過Client來向JavaTest要求某個測試程式的子測試項目與傳送測試完成的結果,當這個測試程式結束時,Java Application Manager會再向Server端要求下個測試程式,直至所有的測試程式皆測試完成。MIDP TCK明確定義了Server與Client的介面,可依照協定的不同,來實作Server與Cleint介面。舉例來說,JavaTest和 Client之間預設的溝通介面是透過TCP/IP,但是在手機平台上未必會存在ethernet,此時就可以提供自行定義的Server及Client 介面,透過其他的溝通介面(如RS232)來進行TCK驗證。
當我們實作Server與Client介面時,也必須考慮Java Application Manager所使用的傳輸協定,對於目前MIDP的RI中,Java Application Manager是透過socket來傳送資料,因此,當我們在實作Server與Client介面時,也必須依照所使用的傳輸協定對Java Application Manager加以修改。
7. 結論
目前我們已經移植Java虛擬機器和MIDP到手機環境上,而移植的成功與否端看是否完整通過Sun的TCK測試,由於實際的手機上無Ethernet,所以我們也修改了相關的程式碼使得Sun的測試程式可以在我們手機環境上執行。在完成了移植之後,我們的下一階段目標,便是要讓Java可以執行的更快,我們目前已經透過組合語言的方式修改KVM的直譯器來加速Java虛擬機器的執行,下一階段的目標是希望透過簡單的just-in-time compiler的方式讓Java的程式速度更快,好讓Java能夠在手機上能有更多樣化的應用
阅读(639) | 评论(0) | 转发(0) |