每個Java開發者都知道Java字節碼是執行在JRE((Java Runtime Environment Java運行時環境)上的。JRE中最重要的部分是Java虛擬機(JVM),JVM負責分析和執行Java字節碼。Java開發人員并不需要去關心JVM是如何運行的。在沒有深入理解JVM的情況下,許多開發者已經開發出了非常多的優秀的應用以及Java類庫。不過,如果你了解JVM的話,你會更加了解Java的,并且你會輕松解決那些看似簡單但是無從下手的問題。
因此,在這篇文件里,我會闡述JVM是如何運行的,包括它的結構,它如何去執行字節碼,以及按照怎樣的順序去執行,同時我還會給出一些常見錯誤的示例以及對應的解決辦法。最后,我還會講解Java 7中的一些新特性。
虛擬機(Virtual Machine)
JRE是由Java API和JVM組成的。JVM的主要作用是通過Class Loader來加載Java程序,并且按照Java API來執行加載的程序。
虛擬機是通過軟件的方式來模擬實現的機器(比如說計算機),它可以像物理機一樣運行程序。設計虛擬機的初衷是讓Java能夠通過它來實現WORA(Write Once Run Anywhere 一次編譯,到處運行),盡管這個目標現在已經被大多數人忽略了。因此,JVM可以在不修改Java代碼的情況下,在所有的硬件環境上運行Java字節碼。
Java虛擬機的特點如下:
基于棧的虛擬機:Intel x86和ARM這兩種最常見的計算機體系的機構都是基于寄存器的。不同的是,JVM是基于棧的。
符號引用:除了基本類型以外的數據(類和接口)都是通過符號來引用,而不是通過顯式地使用內存地址來引用。
垃圾回收機制:類的實例都是通過用戶代碼進行創建,并且自動被垃圾回收機制進行回收。
通過對基本類型的清晰定義來保證平臺獨立性:傳統的編程語言,例如C/C++,int類型的大小取決于不同的平臺。JVM通過對基本類型的清晰定義來保證它的兼容性以及平臺獨立性。
網絡字節碼順序:Java class文件用網絡字節碼順序來進行存儲:為了保證和小端的Intel x86架構以及大端的RISC系列的架構保持無關性,JVM使用用于網絡傳輸的網絡字節順序,也就是大端。
雖然是Sun公司開發了Java,但是所有的開發商都可以開發并且提供遵循Java虛擬機規范的JVM。正是由于這個原因,使得Oracle HotSpot和IBM JVM等不同的JVM能夠并存。Google的Android系統里的Dalvik VM也是一種JVM,雖然它并不遵循Java虛擬機規范。和基于棧的Java虛擬機不同,Dalvik VM是基于寄存器的架構,因此它的Java字節碼也被轉化成基于寄存器的指令集。
Java字節碼(Java bytecode)
為了保證WORA,JVM使用Java字節碼這種介于Java和機器語言之間的中間語言。字節碼是部署Java代碼的最小單位。
在解釋Java字節碼之前,我們先通過實例來簡單了解它。這個案例是一個在開發環境出現的真實案例的總結。
現象
一個一直運行正常的應用突然無法運行了。在類庫被更新之后,返回下面的錯誤。
1
2
3
|
應用的代碼如下,而且它沒有被改動過。
1
2
3
4
5
|
// UserService.java … public void add(String userName) { admin.addUser(userName); } |
更新后的類庫的源代碼和原始的代碼如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// UserAdmin.java - Updated library source code … public User addUser(String userName) { User user = new User(userName); User prevUser = userMap.put(userName, user); return prevUser; } // UserAdmin.java - Original library source code … public void addUser(String userName) { User user = new User(userName); userMap.put(userName, user); } |
原文轉自:http://www.anti-gravitydesign.com