亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

從一道面試題來認識java類加載時機與過程

2019-11-06 06:39:44
字體:
來源:轉載
供稿:網友

  開門見山

以前曾經看到過一個java的面試題,當時覺得此題很簡單,可是自己把代碼運行起來,可是結果并不是自己想象的那樣。題目如下:

 

12345678910111213141516171819202122class SingleTon {    PRivate static SingleTon singleTon = new SingleTon();    public static int count1;    public static int count2 = 0;     private SingleTon() {        count1++;        count2++;    }     public static SingleTon getInstance() {        return singleTon;    }} public class Test {    public static void main(String[] args) {        SingleTon singleTon = SingleTon.getInstance();        System.out.println("count1=" + singleTon.count1);        System.out.println("count2=" + singleTon.count2);    }}

錯誤答案

 

count1=1

count2=1

 正確答案

 

count1=1

count2=0

為神馬?為神馬?這要從java的類加載時機說起。

2 類的加載時機

類從被加載到虛擬機內存中開始,直到卸載出內存為止,它的整個生命周期包括了:加載、驗證、準備、解析、初始化、使用和卸載這7個階段。其中,驗證、準備和解析這三個部分統稱為連接(linking)。其中,加載、驗證、準備、初始化和卸載這五個階段的順序是確定的,類的加載過程必須按照這種順序按部就班的“開始”(僅僅指的是開始,而非執行或者結束,因為這些階段通常都是互相交叉的混合進行,通常會在一個階段執行的過程中調用或者激活另一個階段),而解析階段則不一定(它在某些情況下可以在初始化階段之后再開始,這是為了支持Java語言的運行時綁定。

3 何時開始類的初始化

什么情況下需要開始類加載過程的第一個階段:"加載"。虛擬機規范中并沒強行約束,這點可以交給虛擬機的的具體實現自由把握,但是對于初始化階段虛擬機規范是嚴格規定了如下幾種情況,如果類未初始化會對類進行初始化。創建類的實例訪問類的靜態變量(除常量【被final修辭的靜態變量】原因:常量一種特殊的變量,因為編譯器把他們當作值(value)而不是域(field)來對待。如果你的代碼中用到了常變量(constant variable),編譯器并不會生成字節碼來從對象中載入域的值,而是直接把這個值插入到字節碼中。這是一種很有用的優化,但是如果你需要改變final域的值那么每一塊用到那個域的代碼都需要重新編譯。訪問類的靜態方法反射如(Class.forName("my.xyz.Test"))當初始化一個類時,發現其父類還未初始化,則先出發父類的初始化虛擬機啟動時,定義了main()方法的那個類先初始化以上情況稱為稱對一個類進行“主動引用”,除此種情況之外,均不會觸發類的初始化,稱為“被動引用”接口的加載過程與類的加載過程稍有不同。接口中不能使用static{}塊。當一個接口在初始化時,并不要求其父接口全部都完成了初始化,只有真正在使用到父接口時(例如引用接口中定義的常量)才會初始化。

4 被動引用例子

子類調用父類的靜態變量,子類不會被初始化。只有父類被初始化。。對于靜態字段,只有直接定義這個字段的類才會被初始化.通過數組定義來引用類,不會觸發類的初始化訪問類的常量,不會初始化類
12345678910111213141516171819class SuperClass {    static {        System.out.println("superclass init");    }    public static int value = 123;} class SubClassextends SuperClass {    static {        System.out.println("subclass init");    }} public class Test {    public static void main(String[] args) {        System.out.println(SubClass.value);// 被動應用1        SubClass[] sca = new SubClass[10];// 被動引用2    }}
程序運行輸出    superclass init                             123從上面的輸入結果證明了被動引用1與被動引用2
123456789101112class ConstClass {    static {        System.out.println("ConstClass init");    }    public static final String HELLOWORLD = "hello world";} public class Test {    public static void main(String[] args) {        System.out.println(ConstClass.HELLOWORLD);// 調用類常量    }}
程序輸出結果hello world從上面的輸出結果證明了被動引用3

5 類的加載過程

5.1 加載

 “加載”(Loading)階段是“類加載”(Class Loading)過程的第一個階段,在此階段,虛擬機需要完成以下三件事情:

       1、 通過一個類的全限定名來獲取定義此類的二進制字節流。

       2、 將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。

       3、 在Java堆中生成一個代表這個類的java.lang.Class對象,作為方法區這些數據的訪問入口。

      加載階段即可以使用系統提供的類加載器在完成,也可以由用戶自定義的類加載器來完成。加載階段與連接階段的部分內容(如一部分字節碼文件格式驗證動作)是交叉進行的,加載階段尚未完成,連接階段可能已經開始。

 

5.2 驗證

 

       驗證是連接階段的第一步,這一階段的目的是為了確保Class文件的字節流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全。

       Java語言本身是相對安全的語言,使用Java編碼是無法做到如訪問數組邊界以外的數據、將一個對象轉型為它并未實現的類型等,如果這樣做了,編譯器將拒絕編譯。但是,Class文件并不一定是由Java源碼編譯而來,可以使用任何途徑,包括用十六進制編輯器(如UltraEdit)直接編寫。如果直接編寫了有害的“代碼”(字節流),而虛擬機在加載該Class時不進行檢查的話,就有可能危害到虛擬機或程序的安全。

      不同的虛擬機,對類驗證的實現可能有所不同,但大致都會完成下面四個階段的驗證:文件格式驗證、元數據驗證、字節碼驗證和符號引用驗證。

       1、文件格式驗證,是要驗證字節流是否符合Class文件格式的規范,并且能被當前版本的虛擬機處理。如驗證魔數是否0xCAFEBABE;主、次版本號是否正在當前虛擬機處理范圍之內;常量池的常量中是否有不被支持的常量類型……該驗證階段的主要目的是保證輸入的字節流能正確地解析并存儲于方法區中,經過這個階段的驗證后,字節流才會進入內存的方法區中存儲,所以后面的三個驗證階段都是基于方法區的存儲結構進行的。

       2、元數據驗證,是對字節碼描述的信息進行語義分析,以保證其描述的信息符合Java語言規范的要求。可能包括的驗證如:這個類是否有父類;這個類的父類是否繼承了不允許被繼承的類;如果這個類不是抽象類,是否實現了其父類或接口中要求實現的所有方法……

       3、字節碼驗證,主要工作是進行數據流和控制流分析,保證被校驗類的方法在運行時不會做出危害虛擬機安全的行為。如果一個類方法體的字節碼沒有通過字節碼驗證,那肯定是有問題的;但如果一個方法體通過了字節碼驗證,也不能說明其一定就是安全的。

       4、符號引用驗證,發生在虛擬機將符號引用轉化為直接引用的時候,這個轉化動作將在“解析階段”中發生。驗證符號引用中通過字符串描述的權限定名是否能找到對應的類;在指定類中是否存在符合方法字段的描述符及簡單名稱所描述的方法和字段;符號引用中的類、字段和方法的訪問性(private、protected、public、default)是否可被當前類訪問

驗證階段對于虛擬機的類加載機制來說,不一定是必要的階段。如果所運行的全部代碼確認是安全的,可以使用-Xverify:none參數來關閉大部分的類驗證措施,以縮短虛擬機類加載時間。

5.3 準備

       準備階段是為類的靜態變量分配內存并將其初始化為默認值,這些內存都將在方法區中進行分配。準備階段不分配類中的實例變量的內存,實例變量將會在對象實例化時隨著對象一起分配在Java堆中。

        public static int value=123;//在準備階段value初始值為0 。在初始化階段才會變為123 。

5.4 解析

       解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程。

       符號引用(Symbolic Reference):符號引用以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能無歧義地定位到目標即可。符號引用與虛擬機實現的內存布局無關,引用的目標并不一定已經加載到內存中。

       直接引用(Direct Reference):直接引用可以是直接指向目標的指針、相對偏移量或是一個能間接定位到目標的句柄。直接引用是與虛擬機實現的內存布局相關的,如果有了直接引用,那么引用的目標必定已經在內存中存在。

5.5 初始化

       類初始化是類加載過程的最后一步,前面的類加載過程,除了在加載階段用戶應用程序可以通過自定義類加載器參與之外,其余動作完全由虛擬機主導和控制。到了初始化階段,才真正開始執行類中定義的Java程序代碼。

        初始化階段是執行類構造器<clinit>()方法的過程。<clinit>()方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態語句塊(static{}塊)中的語句合并產生的。

6 題目分析

上面很詳細的介紹了類的加載時機和類的加載過程,通過上面的理論來分析本文開門見上的題目
12345678910111213141516171819202122class SingleTon {    private static SingleTon singleTon = new SingleTon();    public static int count1;    public static int count2 = 0;     private SingleTon() {        count1++;        count2++;    }     public static SingleTon getInstance() {        return singleTon;    }} public class Test {    public static void main(String[] args) {        SingleTon singleTon = SingleTon.getInstance();        System.out.println("count1=" + singleTon.count1);        System.out.println("count2=" + singleTon.count2);    }}

分析:

1:SingleTon singleTon = SingleTon.getInstance();調用了類的SingleTon調用了類的靜態方法,觸發類的初始化2:類加載的時候在準備過程中為類的靜態變量分配內存并初始化默認值 singleton=null count1=0,count2=03:類初始化化,為類的靜態變量賦值和執行靜態代碼快。singleton賦值為new SingleTon()調用類的構造方法4:調用類的構造方法后count=1;count2=15:繼續為count1與count2賦值,此時count1沒有賦值操作,所有count1為1,但是count2執行賦值操作就變為0
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产亚洲精品日韩| 国产精品成久久久久三级| 中文字幕精品在线视频| 中文字幕亚洲综合| 亚洲欧洲一区二区三区在线观看| 欧美性猛交xxxx黑人| 国产成人精品免高潮在线观看| 亚洲精品91美女久久久久久久| 日韩免费高清在线观看| 成人在线免费观看视视频| 亚洲美女精品成人在线视频| 国产热re99久久6国产精品| 色99之美女主播在线视频| 日韩成人中文字幕| 77777少妇光屁股久久一区| 91理论片午午论夜理片久久| 成人国产在线激情| 亚洲毛片在线看| 精品亚洲夜色av98在线观看| 96pao国产成视频永久免费| 欧美精品在线看| 懂色av中文一区二区三区天美| 欧美在线视频观看| 亚洲欧洲日韩国产| 97在线看福利| 国产精品美女视频网站| 77777少妇光屁股久久一区| 欧美裸体视频网站| 亚洲国模精品一区| 91精品国产91久久| 久久久久久中文| 欧美人交a欧美精品| 久久精品国产亚洲| 久久国内精品一国内精品| 成人国产精品久久久久久亚洲| 亚洲xxx大片| 97在线视频免费播放| 在线观看久久久久久| 青草青草久热精品视频在线观看| 久久久在线视频| 久久的精品视频| 日韩暖暖在线视频| 精品国产一区二区三区久久狼5月| 亚洲国产精品yw在线观看| 欧美成人合集magnet| 亚洲国产精久久久久久| 国产精品九九久久久久久久| 国产69久久精品成人看| 国产精品美女午夜av| 欧美激情2020午夜免费观看| 成人国产精品久久久| 国产精品网站大全| 久久精品在线视频| 国产亚洲日本欧美韩国| 97成人在线视频| 亚洲欧美三级伦理| 欧美国产中文字幕| 欧美激情在线一区| 国产亚洲福利一区| 欧美夜福利tv在线| 国产精品精品视频| 亚洲а∨天堂久久精品9966| 一本一本久久a久久精品综合小说| 日韩一区二区av| 国产精品永久免费| 亚洲精品自拍第一页| 欧美性理论片在线观看片免费| 国产91色在线|| 亚洲欧美国产日韩天堂区| 欧美日韩在线一区| 一个色综合导航| 亚洲综合成人婷婷小说| 国产美女高潮久久白浆| 亚洲国产91精品在线观看| 欧美另类69精品久久久久9999| 欧美色图在线视频| 欧美午夜无遮挡| 欧美激情图片区| 欧洲一区二区视频| 国产精品美女午夜av| 色视频www在线播放国产成人| 懂色aⅴ精品一区二区三区蜜月| 中文字幕日韩精品在线观看| 国产精品视频网站| 日韩av网站导航| 亚洲视频一区二区三区| 亚洲日韩第一页| 国产91精品视频在线观看| 亚洲伦理中文字幕| 亚洲精品国产精品自产a区红杏吧| 91综合免费在线| 欧美日韩亚洲视频一区| 久久久久中文字幕| 国产精品美女av| 亚洲码在线观看| 深夜福利一区二区| 久久激情视频免费观看| 成人a级免费视频| 欧美—级a级欧美特级ar全黄| 欧美激情亚洲自拍| 欧美裸体xxxx极品少妇| 成人免费淫片视频软件| 国产亚洲精品久久久优势| 91国内在线视频| 欧美激情精品久久久久久变态| 成人自拍性视频| 成年无码av片在线| 日韩有码视频在线| 高跟丝袜欧美一区| 欧美日韩一区二区免费在线观看| 欧美午夜女人视频在线| 日韩成人激情影院| 中文国产成人精品久久一| 国产91亚洲精品| 日韩禁在线播放| 国产免费亚洲高清| 日韩欧美在线视频日韩欧美在线视频| 一区二区三区无码高清视频| 国产亚洲精品日韩| 欧美日韩国产一区中文午夜| 欧美性猛xxx| 国产精品xxxxx| 8x拔播拔播x8国产精品| 97热在线精品视频在线观看| 国产丝袜高跟一区| 91精品综合视频| 亚洲毛片在线免费观看| 欧美电影在线观看高清| 亚洲欧洲黄色网| 久久久久久久久久久久久久久久久久av| 国产精品人成电影| 国产精品69久久| 亚洲2020天天堂在线观看| 欧美整片在线观看| 日韩精品欧美国产精品忘忧草| 日韩在线视频网| 亚洲精品国产成人| 国产精品日日做人人爱| 国产日韩欧美成人| 久99久在线视频| 国产精品自产拍高潮在线观看| 国产精品自产拍在线观看中文| 国内精久久久久久久久久人| 91牛牛免费视频| 国产精品久久久久久影视| 亚洲色无码播放| 久久免费精品日本久久中文字幕| 在线播放国产一区二区三区| 青青草国产精品一区二区| 国产精品日韩欧美大师| 欧美xxxx做受欧美.88| 久久精品中文字幕| 久久亚洲国产精品成人av秋霞| 国内精品视频久久| 97精品欧美一区二区三区| 国内精品在线一区| 亚洲精品小视频在线观看| 欧美大片在线免费观看| 久久久久久av| 一本色道久久综合亚洲精品小说| 日韩最新av在线| 成人免费在线视频网址| 亚洲欧美一区二区激情| 亚洲色无码播放|