18年轉眼就3月份都快結束了,也就是說一個季度就結束了;而我也因為年前筆記本壞了,今天剛修好了,那么也應該繼續學習和博客之旅了。今年的博客之旅,從JVM開始學起,下面我們就言歸正傳,進入正題。
一、Java虛擬機與程序的生命周期
一個運行時的Java虛擬機(JVM)負責運行一個Java程序。
當啟動一個Java程序時,一個虛擬機實例誕生;當程序關閉退出,這個虛擬機實例也就隨之消亡.
如果在同一台計算機上同時運行多個Java程序,將得到多個Java虛擬機實例,每個Java程序都運行於它自己的Java虛擬機實例中。
在如下幾種情況下,Java虛擬機將結束生命周期:
1.執行了System.exit()方法
2.程序正常執行結束
3.程序在執行過程中遇到了異常或錯誤而異常終止
4.由於操作系統出現錯誤而導致Java虛擬機進程終止
二、類加載器ClassLoader
上面我們提到了java 程序是基於JVM之上運行的,那么我們知道我們編寫的java程序,首先java編譯器將我們的源代碼編譯成為字節碼,然后由JVM將字節碼load到內存中,接着我們的程序就可以創建對象了,我們知道JVM將字節碼load到內存之后將將建立內存模型(JVM的內存模型我們將在稍后闡述),那JVM是怎么將類load到內存中的呢?對了,是通過Classloader;也就是我們說的類加載器。在講解具體類加載執行流程前,我們來看一段代碼:
class Singleton{ private static Singleton singleton=new Singleton(); private static int counter1; private static int counter2 = 0; public Singleton() { counter1++; counter2++; } public static int getCounter1() { return counter1; } public static int getCounter2() { return counter2; } public static Singleton getInstance(){ return singleton; } } public class ClassLoaderTest { @SuppressWarnings("static-access") public static void main(String[] args) { Singleton singleton=Singleton.getInstance(); System.out.println("counter1:"+singleton.getCounter1()); System.out.println("counter2:"+singleton.getCounter2()); } }
我們先猜測一下運行結果,然后我們再來調換一下單實例生成的順序,將:
private static Singleton singleton=new Singleton(); private static int counter1; private static int counter2 = 0;
修改為:
private static int counter1; private static int counter2 = 0; private static Singleton singleton=new Singleton();
然后我們會驚奇的發現,竟然結果是不一樣的,這又是為什么呢? 學過JVM的的類加載器過程的估計一定知道了,但沒有學過的,那么不要急,讓我們一起來揭秘。
三、類的加載流程
緊接着上面的類型,讓我們來看下類加載器到底是如何來加載的,流程如下:
即類加載經歷了:加載 --> 連接 --> 初始化
1.加載:查找並加載類的二進制數據。
加載就是將二進制的字節碼通過IO輸入到JVM中,我們的字節碼是存在於硬盤上面的,而所用的類都必須加載到內存中才能運行起來,加載就是通過IO把字節碼從硬盤遷移到內存中。
詳細分析見:《JVM學習二:JVM之類加載器之加載分析》:http://www.cnblogs.com/pony1223/p/8641015.html
2.連接:連接又分為三個步驟:
驗證:確保被加載類的正確性。
即驗證class文件是否符合JVM的要求。
准備:為類的靜態變量分配內存,並將其初始化為默認值。
解析:把類中的符號引用轉換為直接引用。
詳細分析見:《JVM學習三:JVM之類加載器之連接分析》:http://www.cnblogs.com/pony1223/p/8641083.html
3.初始化:
為類的靜態變量賦予正確的初始值,即在程序里為靜態變量指定的初始值,或靜態代碼塊中的賦值操作。
靜態代碼塊是從上到下順序執行的,可以對一個靜態變量多次賦值,最后的結果為靜態變量的初始值。
詳細分析見:《JVM學習四:JVM之類加載器之初始化分析》:http://www.cnblogs.com/pony1223/p/8641181.html
參考資料:
聖思園張龍老師深入Java虛擬機系列