Java內存分析
瞭解:類的加載過程
類的加載與ClassLoader的理解
練習代碼
// 類如何加載的?
public class Test05 {
public static void main(String[] args) {
A a = new A();
System.out.println(A.m);
/*
* 1、加載到內存,會產生一個類對應的 Class對象
* 2、鏈接 ,鏈接結束後 m = 0(剛開始賦值默認值爲0)
* 3、初始化(調用 clinit 方法,並進行合併)
* 通過<clinit>(){
* System.out.println("A類靜態代碼塊初始化");
m = 300;
m = 100;
* }方法初始化(拿代碼進來(上面的三行代碼拿進來))
*
* 此時 m = 100
*/
}
}
class A{
static {
System.out.println("A類靜態代碼塊初始化");
m = 300;
}
static int m = 10;
public A(){
System.out.println("A類的無參構造初始化");
}
}
代碼內存分析
1、剛開始加載類時(類的數據、靜態變量、靜態方法、常量池、代碼)
2、類加載完成立馬產生一個Class對象(生成一個Java.lang.Class對象 代表 Test05這個類、生成一個Java.lang.Class對象 代表 A這個類),在加載的時候就形成了這兩個對象,這兩個Class對象就包含了這個類所有的東西
上面爲(加載:將class文件字節碼內容加載到內存中,並將這些靜態數據轉換成方法區的運行時數據結構,然後生成一個代表這個類的java.lang.Class對象.)
3、下面開始準備執行main()方法了,此時首先 m 默認爲0(m = 0)(這裏匹配鏈接階段的準備階段:正式爲類變量(static)分配內存並設置類變量默認初始值的階段,這些內存都將在方法區中進行分配)
鏈接階段的 m爲0(m = 0)
當準備階段都做完了,就會執行 A a = new A();
4、new A()在堆內存中,這個動作會產生一個A類新的對象(這個對象會去找它自己(A類)的那個Class類,無論創建多少個A類的對象,它的Class類只有一個),它會指向A類的Class,這時就能拿到A類的所有東西(它會去找A類的Class(在堆內存指向),因爲 Class 擁有A類的所有數據,然後通過這些數據,就可以給A類顯示賦值了,然後初始化,此時初始化時會執行一個方法()方法,它會把靜態代碼塊的初始值合併了)
5、合併靜態代碼塊(合併 m = 300 和 m = 100),這兩句話相當於重新賦值給 m(第一次給m賦值爲300第二次賦值爲100,並把前面的值被覆蓋了,於是上面的 A.m打印出來的爲100,它是在初始化的時候執行的(把靜態代碼塊合併起來),通過A類的具體對象給它賦值,賦值完通過 初始化,這次就有一個初始值,就可以打印出來了)