java 執行過程 運行原理

Java的運行原理

在Java中引入了虛擬機的概念,即在機器和編譯程序之間加入了一層抽象的虛擬的機器。這臺虛擬的機器在任何平臺上都提供給編譯程序一個的共同的接口。編譯程序只需要面向虛擬機,生成虛擬機能夠理解的代碼,然後由解釋器來將虛擬機代碼轉換爲特定系統的機器碼執行。在Java中,這種供虛擬機理解的代碼叫做字節碼(ByteCode),它不面向任何特定的處理器,只面向虛擬機。每一種平臺的解釋器是不同的,但是實現的虛擬機是相同的。Java源程序經過編譯器編譯後變成字節碼,字節碼由虛擬機解釋執行,虛擬機將每一條要執行的字節碼送給解釋器,解釋器將其翻譯成特定機器上的機器碼,然後在特定的機器上運行。

Java虛擬機(JVM)

Java虛擬機(JVM)是Java VirtualMachine的縮寫,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能模擬來實現的。

java中,類加載器把一個類裝入JAVA虛擬機需要經過三個步驟來完成:裝載、鏈接、初始化,其中鏈接又分來校驗、準備、解析過程

裝載:查找和導入.class文件

連接:檢查裝入.class文件的正確性,然後,java虛擬機爲變量分配內存,設置默認值

初始化:把符號引用變成直接引用。

 

  1. public class Main { 
  2. private static int size=1
  3. public static void main(String args[]) {  
  4. User u = new User(); 
  5. u.setName("李文水"); 
  6. u.setPwd("159");  
  7. String name = u.getName(); 
  8. String pwd = u.getPwd(); 
  9. u = null
  10. }  
  11. }  
  12. public class User { 
  13. private String name; 
  14. private String pwd; 
  15. public String getName() { 
  16. return name; 
  17. }  
  18. public void setName(String name) { 
  19. this.name = name; 
  20. }  
  21. public String getPwd() { 
  22. return pwd; 
  23. }  
  24. public void setPwd(String pwd) { 
  25. this.pwd = pwd; 
  26. }  

現在假設這兩個java源文件已經被編譯成了CLASS文件了,我們來看看java虛擬機怎麼執行的。

Java虛擬機工作流程:

1.裝載

描敘:Java虛擬機裝載指定的CLASS文件,

結果:形成這個CLASS類的實例對象

過程:java虛擬機使用類裝載器定位到相應的CLASS文件,然後讀取這個CLASS文件(一個線性二進制數據流),將它傳入java虛擬機中。緊接着虛擬機提取其中的類型信息。比如:該類的類名,方法名,變量名,修飾符,方法的返回類型等等。還有一個重要的東西就是常量池。(常量池保存了該類型的所有常量,包括直接常量和對其他類型,字段,方法的符號引用)將這些信息保存在一個叫做方法區的地方。最終形成CLASS類的實例,這個實例存放在內存的堆區。它成爲了java程序與內部數據結構之間的接口,程序要訪問該類型的信息,程序就調用該類型對應的CLASS實例對象的方法。簡而言之:這個過程就是把一個類型的二進制數據解析爲方法區中的內部數據結構,並在堆上建立一個CLASS對象的過程。

示例:裝載Main類

Java虛擬機讀取Main類的CLASS文件,生產對應的java.lang.Class類的實例,讀取其中的類型信息,比如修飾符private,public,static,另外變量size,name,pwd,User(User即爲一個引用)共同構成了這個類的常量池。將這些信息保存在方法區,

2.連接

描述:驗證,準備,解析(可選)

結果:這個類型是正確的。(這裏不知道該怎麼描述)

過程:

1)驗證:確定類型符合java語言的語義,比如:final類不能有子類,final方法不能被覆蓋,確保在類型和超類型之間沒有不兼容的方法聲明(比如兩個方法擁有同樣的名字,參數完全相同,但返回類型不同)。

2)準備:java虛擬機爲類變量分配內存,設置默認值

3)解析:在類型的常量池中尋找類,接口,字段和方法的符合引用把這些符號引用替換成直接引用的過程。

示例: 連接Main類

Java虛擬機爲size分配內存,並賦默認值0.找到常量池中User類的引用,如果User類還沒有被裝載,則裝載並且連接該類,然後將常量池中對User類的引用替換爲直接引用。在此時User類並不會被初始化,因爲還沒有用它。

3.初始化

描述:初始化一些靜態變量

結果:這個類型可以使用了

過程:可能會調用()方法,(這個方法只能夠由java虛擬機調用)來初始化該類的靜態變量。在調用這個方法前,必須確認該類的超類的()方法已經被調用。

示例:初始化Main類

Java虛擬機將Main類的靜態變量賦值爲1.

4.使用(執行該類代碼了)

1.User u = new User();(存放在內存的堆區)

創建了一個User類實例,實際上是通過這個類的CLASS實例實例化的。方法如下:

User u=(User)Class.forName("User").newInstance();

爲了方便,用C代替Class.forName("User")

2.u.setName("李文水"); u.setPwd("159");

調用該類的方法,爲該類的變量賦值,Java虛擬機內部調用是這樣的,通過方法區找到該方法,利用CLASS實例的如下方法調用:

c.getMethod("setName").invoke(u,"李文水");

3.String name = u.getName(); String pwd = u.getPwd();

與第二步類似,不同的是將取得的值分別賦給了變量name和pwd。關鍵是這個值保存在哪裏?和實例對象一樣,存放在堆區。這個時候我應該可以看出CLASS實例的作用了,它就是起箇中間作用,將程序中的調用反應到堆區上數據的變化。

4.u = null;


這個步驟寫出來的目的是瞭解一下Java虛擬機垃圾回收機制。(沒有什麼實際意義)



當執行 u =null;時這條線就被斬斷了,因此User實例就不可以觸及了,所以java虛擬機就可以回收這個User實例了


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章