第七篇 JVM核心机制之JVM运行和类加载全过程(二)
分析:? ?
說明:
內存中存在棧、堆(放創建好的對象)、方法區(實際也是一種特殊堆)
1、JVM加載Demo01時候,首先在方法區中形成Demo01類對應靜態數據(類變量、類方法、代碼…),同時在堆里面也會形成java.lang.Class對象(反射對象),代表Demo01類,通過對象可以訪問到類二進制結構。然后加載變量A類信息,同時也會在堆里面形成a對象,代表A類。
2、main方法執行時會在棧里面形成main方法棧幀,一個方法對應一個棧幀。如果main方法調用了別的方法,會在棧里面挨個往里壓,main方法里面有個局部變量A類型的a,一開始a值為null,通過new調用類A的構造器,棧里面生成A()方法同時堆里面生成A對象,然后把A對象地址付給棧中的a,此時a擁有A對象地址。
3、當調用A.width時,調用方法區數據。?
當類被引用的加載,類只會加載一次
?
類的主動引用(一定會發生類的初始化)
①new一個類的對象
②調用類的靜態成員(除了final常量)和靜態方法
③使用java.lang.reflect包的方法對類進行反射調用
④當虛擬機啟動,java Demo01,則一定會初始化Demo01類,說白了就是先啟動main方法所在的類
⑤當初始化一個類,如果其父類沒有被初始化,則先初始化它父類
類的被動引用(不會發生類的初始化)
①當訪問一個靜態域時,只有真正聲名這個域的類才會被初始化
②通過子類引用父類的靜態變量,不會導致子類初始化
③通過數組定義類的引用,不會觸發此類初始化
④引用常量不會觸發此類的初始化(常量在編譯階段就存入調用類的常量池中了)
?
1 public class Demo01 { 2 static{ 3 System.out.println("靜態初始化demo01"); 4 } 5 6 public static void main(String[] args) { 7 System.out.println("靜態初始化demo01.main"); 8 /*String str = "aaa"; 9 int a = 23435;*/ 10 //調用A類的方法 11 A a = new A(); 12 13 //通過反射調用 14 /* try { 15 Class.forName("com.zzp.A"); 16 } catch (ClassNotFoundException e) { 17 e.printStackTrace(); 18 }*/ 19 20 //注意打印出來的width的值和程序執行的順序 21 //主動引用 22 // System.out.println(a.width); 23 24 //被動引用 25 // System.out.println(a.b); 26 27 //數組初始化 28 //A[] as = new A[10]; 29 30 System.out.println(B.width); 31 } 32 } 33 34 //創建一個B類,繼承A 35 class B extends A{ 36 static{ 37 System.out.println("靜態初始化B"); 38 } 39 } 40 41 42 class A extends A_Father{ 43 public static int width = 100; 44 public static final int b= 100; 45 static{ 46 System.out.println("靜態初始化A"); 47 width = 300; 48 } 49 public A(){ 50 System.out.println("創建A類的對象"); 51 } 52 } 53 54 class A_Father{ 55 static{ 56 System.out.println("靜態初始化A_Father"); 57 } 58 }
?
轉載于:https://www.cnblogs.com/zhangzhipeng001/p/9135690.html
總結
以上是生活随笔為你收集整理的第七篇 JVM核心机制之JVM运行和类加载全过程(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: node.js实现国标GB28181流媒
- 下一篇: 有什么办法可以除去下水道的臭味?