Docker系列之四:建立掛載nginx、mysql、redis、tomcta、ftp容器
一個類從載入到虛擬機器記憶體到從記憶體解除安裝的整個生命週期包括七個階段:載入、驗證、準備、解析、初始化、使用和解除安裝。驗證、準備和分析統稱為連結,
載入、驗證、準備、初始化、解除安裝的順序是確定的,一個類的載入過程必須按照這個順序一步步開始,而解析階段在某些情況下不一定需要在初始化階段之後開始,這是為了支援Java語言的執行時繫結(也稱為動態繫結)。接下來,我們將解釋載入、驗證、準備、解析和初始化五個步驟,它們構成了一個完整的類載入過程。使用沒什麼好說的,解除安裝屬於GC的工作在之前的GC文章裡已經提到過了。
裝載裝載
載入是類載入的第一階段。有兩種機會可以觸發類載入:
1.預載。當虛擬機器啟動時,它會載入。JAVA_HOME/lib/下rt.jar中的類檔案。這個jar包中的內容是程式執行時經常用到的,比如java.lang.、java.util.
2.執行時載入。當虛擬機器使用. class檔案時,它會轉到記憶體中檢查。載入了類檔案。如果沒有,它將根據類的完全限定名載入該類。
那麼,載入階段做了什麼呢?事實上,載入階段做了三件事: %E6%B2%88%E9%98%B3%E4%BB%A3%E5%AD%95%E6%9C%BA%E6%9E%84(%E7%94%B5%E5%BE%AE133%E4%B9%808765%E4%B9%806644%E5%90%8C%E6%AD%A5)%E5%8C%85%E7%94%B7%E5%A5%B3%E5%AE%9D%E5%AE%9D
static
{
System.out.println("ConstCLass init");
}
}
public class TestMain
{
public static void main(String[] args)
{
System.out.println(ConstClass.HELLOWORLD);
}
}
執行結果為
Hello World
初始化一個類,發現它的父類還沒有初始化
當虛擬機器啟動時,虛擬機器將初始化使用者指定的包含main()方法的類
除了以上四種場景,所有引用類的方法都不會觸發類的初始化,這就是所謂的被動引用。接下來,我們來看幾個被動引用的例子:
1.子類是指父類的靜態欄位,不會引起子類初始化。至於子類是否被載入和驗證,前者可以通過“-XX:+TraceClassLoading”檢視
在編譯階段,通過常量傳播優化,常量HELLOWORLD的值“Hello World”實際上已經儲存在NotInitialization類的常量池中。將來,NotInitialization對常量ConstClass的引用。HELLOWORLD實際上已經被轉換成NotInitialization類對自己的常量池的引用。也就是說,實際上NotInitialization的Class檔案中沒有const Class的符號引用條目,編譯成類後這兩個類之間也沒有任何聯絡。