Java 執(zhí)行過程

Java的運行原理

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

Java 虛擬機 (JVM)

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

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

  • 裝載:查找和導入.class文件
  • 連接:檢查裝入.class文件的正確性,然后,java虛擬機為變量分配內(nèi)存,設置默認值
  • 初始化:把符號引用變成直接引用。
public class Main {
    private static int size = 1;
    public static void main(String args[]) {
        User u = new User();
        u.setName("李文水");
        u.setPwd("159");
        String name = u.getName();
        String pwd = u.getPwd();
        System.out.println("姓名:"+u.getName());
        u=null;
    }
}
class User {
    private String name;
    private String pwd;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}

Java虛擬機工作流程

1、裝載

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

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

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

示例:裝載Main類

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

2、連接

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

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

過程:

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

2)準備:java虛擬機為類變量分配內(nèi)存,設置默認值

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

示例: 連接Main類

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

3、初始化

描述:初始化一些靜態(tài)變量

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

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

示例:初始化Main類

Java虛擬機將Main類的靜態(tài)變量賦值為1.

4、執(zhí)行

  • User u = new User();(存放在內(nèi)存的堆區(qū))

創(chuàng)建了一個User類實例,實際上是通過這個類的CLASS實例實例化的。方法如下:User u=(User)Class.forName("User").newInstance();
為了方便,用C代替Class.forName("User")

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

調(diào)用該類的方法,為該類的變量賦值,Java虛擬機內(nèi)部調(diào)用是這樣的,通過方法區(qū)找到該方法,利用CLASS實例的如下方法調(diào)用:
c.getMethod("setName").invoke(u,"李文水");

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

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

  • u = null;

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

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • JAVA虛擬機的生命周期 一個運行時的Java虛擬機實例的天職是:負責運行一個java程序。當啟動一個Java程序...
    Solang閱讀 1,184評論 0 19
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內(nèi)部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,778評論 18 399
  • 【原創(chuàng)詩歌】 條紋衫穿在我身上但是沒有看過你 文/伊寧 再沒聽過如此沉悶的夜雨,一朵壓住一朵 呼吸。瓦楞有北方的木...
    簡思莼閱讀 155評論 0 0
  • ?文/趙暖暖 1. 暖暖最近愛上了跑步。 今天跑了一條不熟悉的路,沿著家附近的一所重點中學的校園慢跑。身體動起來...
    暖心手繪心理課閱讀 518評論 0 2
  • 武老師的心理課,我都聽了60多節(jié)了,生活中,我總是會覺得自己聽了很多大道理依然過不好這一生,其實是我自己看不見自身...
    郭郭88閱讀 591評論 0 0