編程語言有兩種:
1、編譯型語言 將代碼一次性編譯成計算機可識別的二進制文件,語言有C和C++
2、解釋型語言 通過解釋器,一行行讀取我們編寫的代碼轉換成二進制數據後執行,JVM就是解釋器,語言有java和kotlin
類的生命週期:
一、類的加載
在加載的時候,虛擬機將我們寫的.java文件,編譯成字節碼後加載到內存裏,然後在內存中生成一個java.lang.Class對象,作爲方法區這個類的各種數據的訪問入口。
二、類的連接
類的加載過程後生成了類的java.lang.Class對象,接着會進入連接階段,連接階段負責將類的二進制數據合併入JRE(Java運行時環境)中。類的連接大致分三個階段。
1、驗證:驗證此class字節流是安全的、沒有被修改的、可以被正常使用的.
2、準備:爲類的靜態變量(static)在方法區分配內存,並賦默認初值(0值或null值)。
如static int a = 5; 靜態變量a被賦默認值0。
靜態常量(static final)會被賦程序設定的初值。
如static final int a = 5; 靜態常量a就會在準備階段被直接賦值爲5,而靜態變量是在初始化階段進行的。
對於一般的成員變量是在類實例化時候,隨對象一起分配在堆內存中。
3、解析:JVM將常量池中的符號引用轉換成直接引用的過程。
三、類的初始化
類初始化是類加載的最後一步,除了加載階段,用戶可以通過自定義的類加載器參與,其他階段都完全由虛擬機主導和控制。到了初始化階段才真正執行Java代碼。
類的初始化的主要工作是爲靜態變量賦程序設定的初值。
如static int a = 100;在準備階段,a被賦默認值0,在初始化階段就j會被賦值爲100。
java虛擬機規範中嚴格規定了有且只有五種情況必須對類進行初始化:
1、使用new字節碼指令創建類的實例,或者使用getstatic、putstatic讀取或設置一個靜態字段的值(放入常量池中的常量除外),或者調用一個靜態方法的時候,對應類必須進行過初始化。
2、通過java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行過初始化,則要首先進行初始化。
3、當初始化一個類的時候,如果發現其父類沒有進行過初始化,則首先觸發父類初始化。
4、當虛擬機啓動時,用戶需要指定一個主類(包含main()方法的類),虛擬機會首先初始化這個類。
5、使用jdk1.7的動態語言支持時,如果一個java.lang.invoke.MethodHandle實例最後的解析結果REF_getStatic、REF_putStatic、RE_invokeStatic的方法句柄,並且這個方法句柄對應的類沒有進行初始化,則需要先觸發其初始化。