1. 程式人生 > >Java程式的執行機制和Java虛擬機器

Java程式的執行機制和Java虛擬機器

1、java程式的執行

Java中原始檔字尾為*.java,編譯(也就是javac命令)使*.java檔案轉換為*.class檔案,然後在計算機上執行(java命令)*.class檔案。這就是java程式的執行過程,那麼JVM(java虛擬機器)是做什麼用的哪?

首先我們來看一下JVM做什麼用的,來看下圖。JVM是讀取和處理*.class檔案。所有的*.class檔案都是在JVM上執行的;JVM負責與不同的作業系統進行匹配。

2、JVM、 JDK、 JRE到底是什麼

JVM -- java virtual machine

JVM就是我們常說的java虛擬機器,它是整個java實現跨平臺的 最核心的部分,所有的java程式會首先被編譯為.class的類檔案,這種類檔案可以在虛擬機器上執行,也就是說class並不直接與機器的作業系統相對應,而是經過虛擬機器間接與作業系統互動,由虛擬機器將程式解 釋給本地系統執行。

JVM 的主要工作是解釋自己的指令集(即位元組碼)到 CPU 的指令集或 OS 的系統呼叫,保護使用者免被惡意程式騷擾。 JVM 對上層的 Java 原始檔是不關心的,它關注的只是由原始檔生成的類檔案( classfile )。類檔案的 組成包括 JVM 指令集,符號表以及一些補助資訊。

JRE -- java runtime environment

 JRE是指java執行環境。光有JVM還不能完成class的 執行,因為在解釋class的時候JVM需要呼叫解釋所需要的類庫lib。 在JDK的安裝目錄裡你可以找到jre目錄,裡面有兩個資料夾bin和lib,在 這裡可以認為bin裡的就是jvm,lib中則是jvm工作所需要的類庫,而jvm和 lib和起來就稱為jre。所以,在你寫完java程式編譯成.class之後,你可以把這個.class檔案 和jre一起打包發給朋友,這樣你的朋友就 可以執行你寫程式了。(jre裡有執行.class的java.exe)

JDK -- java development kit

JDK是java開發工具包,基本上每個學java的人都會先在機器 上裝一個JDK,那他都包含哪幾部分呢?讓我們看一下JDK的安裝目錄。在目錄下面有 六個資料夾、一個src類庫原始碼壓縮包、和其他幾個宣告檔案。其中,真正在執行java時起作用的 是以下四個資料夾:bin、include、lib、 jre。現在我們可以看出這樣一個關係,JDK包含JRE,而JRE包 含JVM。

bin:最主要的是編譯器(javac.exe)

include:java和JVM互動用的標頭檔案

lib:類庫

 jre:java執行環境

(注意:這裡的bin、lib資料夾和jre裡的bin、lib是 不同的)總的來說JDK是用於java程式的開發,而jre則 是隻能執行class而沒有編譯的功能。

3、搜到的面試題目

什麼是Java虛擬機器?為什麼Java被稱作是“平臺無關的程式語言”?

Java虛擬機器是一個可以執行Java位元組碼的虛擬機器程序。Java原始檔被編譯成能被Java虛擬機器執行的位元組碼檔案。 
Java被設計成允許應用程式可以執行在任意的平臺,而不需要程式設計師為每一個平臺單獨重寫或者是重新編譯。Java虛擬機器讓這個變為可能,因為它知道底層硬體平臺的指令長度和其他特性。

JDK、JRE、JVM關係是什麼?

JDK(Java Development Kit)即為Java開發工具包,包含編寫Java程式所必須的編譯、執行等開發工具以及JRE。開發工具如:用於編譯java程式的javac命令、用於啟動JVM執行java程式的java命令、用於生成文件的javadoc命令以及用於打包的jar命令等等。 
JRE(Java Runtime Environment)即為Java執行環境,提供了執行Java應用程式所必須的軟體環境,包含有Java虛擬機器(JVM)和豐富的系統類庫。系統類庫即為java提前封裝好的功能類,只需拿來直接使用即可,可以大大的提高開發效率。 
JVM(Java Virtual Machines)即為Java虛擬機器,提供了位元組碼檔案(.class)的執行環境支援。 

簡單說,就是JDK包含JRE包含JVM。

偶遇這道題目,覺得這個也有詳述的必要,加在此處。

解釋記憶體中的棧(stack)、堆(heap)和方法區(method area)的用法。(下面這段話雖然講的很理論,但對於後期程式除錯有很大的支撐作用)

通常我們定義一個基本資料型別的變數,一個物件的引用,還有就是函式呼叫的現場儲存都使用JVM中的棧空間;而通過new關鍵字和構造器建立的物件則放在堆空間,堆是垃圾收集器管理的主要區域,由於現在的垃圾收集器都採用分代收集演算法,所以堆空間還可以細分為新生代和老生代,再具體一點可以分為Eden、Survivor(又可分為From Survivor和To Survivor)、Tenured;方法區和堆都是各個執行緒共享的記憶體區域,用於儲存已經被JVM載入的類資訊、常量、靜態變數、JIT編譯器編譯後的程式碼等資料;程式中的字面量(literal)如直接書寫的100、”hello”和常量都是放在常量池中,常量池是方法區的一部分,。棧空間操作起來最快但是棧很小,通常大量的物件都是放在堆空間,棧和堆的大小都可以通過JVM的啟動引數來進行調整,棧空間用光了會引發StackOverflowError,而堆和常量池空間不足則會引發OutOfMemoryError。

下面我們看一下JVM執行時資料區(http://blog.csdn.net/liu88010988/article/details/50789895):

第一塊:PC暫存器

PC暫存器是用於儲存每個執行緒下一步將執行的JVM指令,如該方法為native的,則PC暫存器中不儲存任何資訊。

第二塊:JVM

JVM棧是執行緒私有的,每個執行緒建立的同時都會建立JVM棧,JVM棧中存放的為當前執行緒中區域性基本型別的變數(java中定義的八種基本型別:booleancharbyteshortintlongfloatdouble)、部分的返回結果以及Stack Frame,非基本型別的物件在JVM棧上僅存放一個指向堆上的地址

第三塊:堆(Heap

它是JVM用來儲存物件例項以及陣列值的區域,可以認為Java中所有通過new建立的物件的記憶體都在此分配,Heap中的物件的記憶體需要等待GC進行回收。

第四塊:方法區域(Method Area

1)在Sun JDK中這塊區域對應的為PermanetGeneration,又稱為持久代。

2)方法區域存放了所載入的類的資訊(名稱、修飾符等)、類中的靜態變數、類中定義為final型別的常量、類中的Field資訊、類中的方法資訊,當開發人員在程式中通過Class物件中的getNameisInterface等方法來獲取資訊時,這些資料都來源於方法區域,同時方法區域也是全域性共享的,在一定的條件下它也會被GC,當方法區域需要使用的記憶體超過其允許的大小時,會丟擲OutOfMemory的錯誤資訊。

第五塊:執行時常量池(Runtime Constant Pool

存放的為類中的固定的常量資訊、方法和Field的引用資訊等,其空間從方法區域中分配。

第六塊:本地方法堆疊(Native Method Stacks

JVM採用本地方法堆疊來支援native方法的執行,此區域用於儲存每個native方法呼叫的狀態。

這些可以通過JDK的命令列工具進行檢視:可參考http://blog.csdn.net/ochangwen/article/details/52971913

參考:

[1]http://blog.csdn.net/songkai320/article/details/51819046