一、簡單概述:
一個java程序的執行流程可以簡單的分為以下幾個步驟:1.編輯源代碼--->2.編譯階段,生成.class文件,即源文件有編譯器編譯成字節碼文件--->3.類加載器加載字節碼文件--->4.虛擬機加載運行。下面就對這幾個階段進行一個簡單的解析。若有錯誤,歡迎指正!
二、簡單解析:
編輯源代碼階段:編輯編輯源代碼就是在任何一個工具上編寫源代碼,最后生成一個.java文件,這就是我們程序員的日常工作之一,也是最簡單的工作之一。編譯源文件生成.class文件
編譯階段:創建完源文件之后,程序先要被JVM中的java編譯器進行編譯為.class文件。java編譯一個類時,如果這個類所依賴的類還沒有被編譯,編譯器會自動的先編譯這個所依賴的類,然后引用。如果java編譯器在指定的目錄下找不到該類所依賴的類的 .class文件或者 .java源文件,就會報"Cant found sysbol"的異常錯誤。編譯后的字節碼文件格式主要分為兩部分:常量池和方法字節碼。常量池記錄的是代碼出現過的(常量、類名、成員變量等)以及符號引用(類引用、方法引用,成員變量引用等);方法字節碼中放的是各個方法的字節碼。
加載字節碼文件:*.java文件經過javac編譯后得到*.class文件,稱為字節碼文件,*.Class文件是一組以8字節為基礎單位的二進制流,各個數據項目按照嚴格的順序排列在class文件中,中間沒有任何的分隔符,這使得class文件在存儲的內容全部是虛擬機運行程序所必須的,當存儲的數據大於8位就采用大端模式。class文件不像xml等語言有分隔符,所以各種數據類型的排列順序還是數量都是嚴格的。那么在這里我們就要好好談談虛擬機的加載機制了。在class文件中的各種信息,最終都要加載到虛擬機中才能運行和使用,但是虛擬機如何加載這些class文件? (虛擬機的類加載機制,虛擬機把描述類的數據從class文件加載到內存,並對數據進行效驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的java類型。java類運行的過程大概分為兩個步驟:(1)類的加載 (2)類的執行。需要說明的一點的是:JVM主要在程序第一次運行時主動使用類的時候,才會立即去加載。換言之,JVM並不是在運行時就會把所有使用到的類都加載到內存中,而是用到,不得不加載的時候,才加載進來,而且只加載一次!根據上面的程序,詳解該程序運行的詳細步驟:(1)在類路徑下找到編譯好的 java 程序中得到 Test.class 字節碼文件后,在命令行上敲 java Test,系統就會啟動一個 JVM 進程,JVM進程從classpath路徑下找到一個名為Test.class的二進制文件,將Test.class文件中的類信息加載到運行時數據區的方法區中,這一過程叫做類的加載。(只有類信息在方法區
中,才能創建對象,使用類中的成員變量);(2)JVM 找到main方法的主函數入口, 持有一個指向當前類(Test)常量池的指針,而常量池中的第一項是發現是一個對Animal對象的符號引用,並且main方法中第一條指令是Animal animal = new Animal("super_yc"),就是讓JVM創建一個Animal對象,但是方法區中還沒有Animal類的類信息,於是JVM就要馬上的加載Animal類,將Animal類信息放入到方法區中,於是JVM 以一個直接指向方法區 Animal類的指針替換了常量池中第一項的符號引用;(3)加載完Animal類的信息以后,JVM虛擬機就會在堆內存中為一個Animal類實例分配內存,然后調用其構造函數初始化Animal實例,這個實例持有指向方法區的Animal類的類型信息(其中包含有方發表,java動態綁定的底層實現)的引用。(animal指向了Animal對象的引用會自動的放在棧中,字符串常量"super_yc"會自動的放在方法區的常量池中,對象會自動的放入堆區)
(4)當使用 animal.pringName()的時候,JVM根據棧中animal引用找到Animal對象,然后根據Animal對象持有的引用定位到方法區中Animal類的類型信息方法表,獲得pringName()函數的字節碼地址,然后開始運行函數。