首頁
中文書目錄
原文書目錄
 站內快速搜尋
資源中心
Book Series
Special Interest













■好消息,歐萊禮書籍已重新鋪貨至各大書局及網路書店,歡迎讀者選購       ■歡迎各院校採用歐萊禮書籍,學校團購請洽校園服務團隊

[技術短文]

JVM 內的資料處理


Java 語言內建八種基本型態(primitive types),分別是 boolean、char、byte、short、int、long、float、double。你可能會期望 JVM 提供和 Java 語言相同的資料型態支援,但事實上,JVM 和 Java 語言所支援的型態是有一些小差異的,之所以如此,有數個原因,其中一個因素是,JVM 所採用的 op-code 是一個位元組寬:沒有足夠的 op-code 空間來充分對等地處理這些型態,所以必須犧牲某些型態,對某些型態的支援比較少。另一個因素,JVM 是 32-bit 的機器:因為區域變數和 operand stack 的空間都是用來放置 32-bit 的資料,所以對於 64-bit 的 double 和 long 都必須特別處理,而未滿 32-bit 的型態也必須被擴大成為 32-bit 才能處理。

JVM 中最基本的數字型態是 int、long、float、double,JVM 數學運算指令完整地支援此四個型態。比方說,iadd 指令用來進行 operand stack 兩個 int 的相加;isub 指令用來進行 operand stack 兩個 int 的相減;fadd 指令用來進行 operand stack 兩個 float 的相加;fsub 指令用來進行 operand stack 兩個 float 的相減。

float 和 double 使用 IEEE 754 的數字表示法。除了數學指令之外,有一些指令用來比較同型態的兩個數,或是用來轉換數字型態。

如同我們前面提過的,double 和 long 的運算需要額外的技巧方能達成,因為 JVM 的工作單位是 32 位元,而 double 和 long 是 64 位元寬。要處理 double 和 long,必須佔用 operand stack 的兩個位置,或兩個連續區域變數的位置。通常這些細節你可以忽略,因為 JVM 將 double 和 long 的部份細節藏起來了。

在 Java 語言中,byte、short、與 char 型態就和整數、浮點數一樣,有著相同的地位。但是,在 JVM 中,byte、short、與 char 不過是「次級公民」,指令的支援程度不及 int 和 float 的完整。你可以宣告有某欄位儲存一個 byte、short、或 char 的資料,用處理 byte、short、或 char 的相關指令來建立或處理。然而,當你取出此 byte、short、或 char 的欄位值時,它們就會自動轉型為 int 型態,然後你的程式取得的是 int 值。相反地,當你指定某值給 byte、short、或 char 的欄位時,你傳給 JVM 的是 int,但是它會自動被截短為適當的體積。你也可以使用 i2s、i2b、i2c 來截短,使其值在對應型態的合理值範圍內(i2s 用來截短成 short、i2b 用來截短成 byte、i2c 用來截短成 char )。

Java 語言提供了 boolean(布林)型態,其值可以是 true 或 false。JVM 中沒有真正的 boolean 型態,而是用整數型態來替代:0 表示 false,1 表示 true。

在 JVM 中,你可以透過 newarray 來建立 boolean 陣列,你也可以宣告一個 boolean 型態的欄位。當你從 boolean 欄位中取出值,此值不是 0 就是 1。同樣地,設定 boolean 欄位時也只能用整數 0 或 1。因為 JVM 無布林型態,條件式分支運算必須使用整數型態,且行為要傳出布林值時必須使用 ireturn 指令,彷彿是傳出一個 int。

想在 boolean 陣列內存取值必須使用為 byte 陣列所設計的指令,所以若要在 boolean 陣列內放入某值,就必須使用 bastore;若要從 boolean 陣列內取出某值,就用 baload。請注意:JVM 規格書中沒有提到 boolean 陣列在 JVM 體內是如何呈現的,某些 JVM 用 bit 陣列來表示 boolean 陣列,某些 JVM 使用 byte 陣列來表示 boolean 陣列。

JVM 提供了建立和處理 Java 物件和陣列的指令。JVM 其實把陣列當成物件看待(你甚至可以取得陣列的類別,而且陣列和 java.lang.Object 支援相同的 method),不過還是有些指令是陣列專用的(比方說 arraylength 用來得知陣列的長度)。

請注意,JVM 規格書中沒有規定物件在 JVM 的記憶體內是如何實作的,只提到所有的物件都要透過 reference 來定址。如果你熟悉 C/C++ 的話,你可以把「reference」一詞用「pointer」來取代,那麼你就會想通了。reference 和 C/C++ 的 pointer 很像。就和 C++ 的指標一樣,同一個物件可以同時被多個 reference 指到。

雖然 C/C++ 允許對 pointer 進行計算,但是 Java 不允許對 reference 進行計算。對 Java 來說,reference 是一種渾沌未明的型態,不可以被當作數字看待,也不可以被轉成數字型態,或用來修改記憶體內的任意位址。

Java 中只允許使用 reference 來定址物件。Java 不支援物件的「傳值呼叫」(但數字型態的確使用傳值呼叫),物件不可以被內嵌在其它物件內(當然,一個物件可以參照到其它物件)。同樣地,變數不可以包含一個實際的物件,只能包含物件的 reference。

另外,還有一個很特殊的資料型態:returnAddress,這是一種 32-bit 的型態,由 JVM 的 routine 所使用。routine 的功能和 method 相彷彿,但用途特殊,主要是用在例外處理中。雖然 Java 程式中 try/catch/finally 會被編譯成 routine,但 routine 和 returnAddress 型態其實都不能在 Java 語言中直接使用。jsr 和 jsr_w 指令會產生 returnAddress 型態的值,此值必須透過 astore 指令來存到區域變數中,以供稍後 ret 指令使用。

本文作者:蔡學鏞
張貼日期:10/01/2002

| 首頁 | 聯絡我們 |
© 2009, O'Reilly Media, Inc. Taiwan Branch