真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何理解JavaJVM虛擬機(jī)中init和clinit的區(qū)別

如何理解Java JVM虛擬機(jī)中init和clinit的區(qū)別,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比濱海新區(qū)網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式濱海新區(qū)網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋濱海新區(qū)地區(qū)。費(fèi)用合理售后完善,十載實(shí)體公司更值得信賴。

:在jvm第一次加載class文件時(shí)調(diào)用,包括靜態(tài)變量初始化語句和靜態(tài)塊的執(zhí)行。

:在實(shí)例創(chuàng)建出來的時(shí)候調(diào)用,包括調(diào)用new操作符;調(diào)用Class或Java.lang.reflect.Constructor對象的newInstance()方法;調(diào)用任何現(xiàn)有對象的clone()方法;通過java.io.ObjectInputStream類的getObject()方法反序列化。

是對象構(gòu)造器方法,也就是說在程序執(zhí)行 new 一個對象調(diào)用該對象類的 constructor方法時(shí)才會執(zhí)行init方法,而是類構(gòu)造器方法,也就是在jvm進(jìn)行類加載—–驗(yàn)證—-解析—–初始化,中的初始化階段jvm會調(diào)用clinit方法。

instance實(shí)例構(gòu)造器,對非靜態(tài)變量解析初始化,而clinit是class類構(gòu)造器對靜態(tài)變量,靜態(tài)代碼塊進(jìn)行初始化。是由javac添加的靜態(tài)方法,并且在加載類之后由JVM調(diào)用。可以在類字節(jié)碼中使用字節(jié)碼大綱工具看到這種方法。注意,只有當(dāng)一個類需要靜態(tài)初始化時(shí)才添加,具體代碼如下:

public class Test1 {

    static int x  = 1; 

    public static void main(String[] args) throws Exception {

    }

}

public class Test2 {

    static final int x  = 1; 

    public static void main(String[] args) throws Exception {

    }

}

Test1類中有,因?yàn)樗淖兞縳需要使用1初始化;而Test2沒有方法,因?yàn)樗黿是一個常數(shù)。還有一點(diǎn)是Class.forNameboolen intialize參數(shù)確定在加載后是否應(yīng)該初始化類。

在準(zhǔn)備階段,變量已經(jīng)賦過一次系統(tǒng)要求的初始值,而在初始化階段,則根據(jù)程序員通過程序制定的主觀計(jì)劃去初始化類變量和其他資源,或者可以從另外一個角度來表達(dá):初始化階段是執(zhí)行類構(gòu)造器方法的過程。

方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態(tài)語句塊(static{}塊)中的語句合并產(chǎn)生的,編譯器收集的順序是由語句在源文件中出現(xiàn)的順序所決定的,靜態(tài)語句塊中只能訪問到定義在靜態(tài)語句塊之前的變量,定義在它之后的變量,在前面的靜態(tài)語句塊可以賦值,但是不能訪問如下代碼

public class Test{

    static{

        i=0;//給變量賦值可以正常編譯通過

        System.out.print(i);//這句編譯器會提示"非法向前引用"

    }

    static int i=1;

}

虛擬機(jī)JVM會保證在子類的方法執(zhí)行之前,父類的方法已經(jīng)執(zhí)行完畢。 因此在虛擬機(jī)中第一個被執(zhí)行的方法的類肯定是java.lang.Object。由于父類的方法先執(zhí)行,也就意味著父類中定義的靜態(tài)語句塊要優(yōu)先于子類的變量賦值操作,如下代碼中,字段B的值將會是2而不是1。

static class Parent{

    public static int A=1;

    static{

    A=2;

}

    static class Sub extends Parent{

public static int B = A;

    }

    public static void main(String[] args){

System.out.println(Sub.B);

    }

}

注意:接口中屬性都是static final類型的常量,在準(zhǔn)備階段就已經(jīng)初始化完成了。

接口中不能使用靜態(tài)語句塊,但仍然有變量初始化的賦值操作,因此接口與類一樣都會生成方法。 但接口與類不同的是,執(zhí)行接口的方法不需要先執(zhí)行父接口的方法。 只有當(dāng)父接口中定義的變量使用時(shí),父接口才會初始化。另外,接口的實(shí)現(xiàn)類在初始化時(shí)也一樣不會執(zhí)行接口的方法。 

JVM類加載原理

如何理解Java JVM虛擬機(jī)中init和clinit的區(qū)別

1)類的生命周期包括了:加載(Loading)、驗(yàn)證(Verification)、準(zhǔn)備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸載(Unloading)七個階段

2)當(dāng)Java程序需要使用某個類時(shí),JVM會確保這個類已經(jīng)被加載、連接(驗(yàn)證、準(zhǔn)備和解析)和初始化。

3)加載階段:通過一個類的全限定名來獲取此類的二進(jìn)制字節(jié)流;將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu);在java堆中生成一個代表這個類的Class對象,作為方法區(qū)這些數(shù)據(jù)的訪問入口;

4)驗(yàn)證階段:驗(yàn)證是為了確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會危害虛擬機(jī)自身的安全;包括文件格式驗(yàn)證、元數(shù)據(jù)驗(yàn)證、字節(jié)碼驗(yàn)證、符號引用驗(yàn)證;如果驗(yàn)證到輸入的字節(jié)流不符合Class文件的存儲格式,就拋出一個java.lang.VerifyError異?;蚱渥宇惍惓!?/p>

5)準(zhǔn)備階段:準(zhǔn)備階段是正式為類變量分配內(nèi)存并設(shè)置類變量初始值(各數(shù)據(jù)類型的零值)的階段,這些內(nèi)存將在方法區(qū)中進(jìn)行分配。

6) 解析階段:解析階段是在虛擬機(jī)將常量池內(nèi)的符號引用替換為直接引用的過程。符號引用:符號引用以一組符號來描述所引用的目標(biāo),符號可以是任何形式的字面量,只要使用時(shí)能無歧義地定位到目標(biāo)即可。符號引用與虛擬機(jī)實(shí)現(xiàn)的內(nèi)存布局無關(guān),引用的目標(biāo)并不一定已經(jīng)加載到內(nèi)存中。直接引用:直接引用可以是直接指向目標(biāo)的指針、相對偏移量或者一個能間接定位到目標(biāo)的句柄。如果有了直接引用,那引用的目標(biāo)必定已經(jīng)在內(nèi)存中存在。

7)初始化階段:初始化階段是執(zhí)行類構(gòu)造器()方法的過程。

初始化是重點(diǎn),需要清楚以下幾點(diǎn):

1)()方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態(tài)語句塊(static{}塊)中的語句合并產(chǎn)生的,編譯器收集的順序是由語句在源文件中出現(xiàn)的順序決定的。靜態(tài)語句塊只能訪問到定義在靜態(tài)語句塊之前的變量,定義在它之后的變量,在前面的靜態(tài)語句塊中可以賦值,但是不能訪問。

2) 方法與實(shí)例構(gòu)造器()不同,不需要顯示的調(diào)用父類構(gòu)造器,虛擬機(jī)會保證在子類的()方法執(zhí)行之前,父類的()已經(jīng)執(zhí)行完畢。

3)()方法對于類或接口來說不是必須的,如果一個類中沒有靜態(tài)語句塊也沒有對變量的賦值操作,那么編譯器可以不為這個類生成()方法。

4)執(zhí)行接口的()不需要先執(zhí)行父接口的()方法,只有當(dāng)父接口中定義的變量被使用時(shí),父接口才會被初始化。接口的實(shí)現(xiàn)類在初始化時(shí)也不會執(zhí)行接口的()方法。

5)虛擬機(jī)會保證一個類的()方法在多線程環(huán)境中被正確的加鎖和同步,如果多個線程同時(shí)去初始化一個類,則只會有一個線程去執(zhí)行這個類的()方法,其他線程需要阻塞等待。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。


分享題目:如何理解JavaJVM虛擬機(jī)中init和clinit的區(qū)別
鏈接URL:http://weahome.cn/article/ppdohi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部