在2008年和2009年,Oracle公司分別收購了BEA公司和Sun公司,這樣Oracle就同時(shí)擁有了兩款優(yōu)秀的java虛擬機(jī):JRockit VM和HotSpot VM。Oracle公司宣布在不久的將來(大約應(yīng)在發(fā)布JDK 8的時(shí)候)會完成這兩款虛擬機(jī)的整合工作,使之優(yōu)勢互補(bǔ)。整合的方式大致上是在HotSpot的基礎(chǔ)上,移植JRockit的優(yōu)秀特性,譬如使用JRockit的垃圾回收器與MissionControl服務(wù),使用HotSpot的JIT解釋與編譯 混合混合的運(yùn)行時(shí)系統(tǒng)。HotSpot VM的熱點(diǎn)代碼探測能力可以通過執(zhí)行計(jì)數(shù)器找出最具有編譯價(jià)值的代碼,然后通知JIT編譯器以方法為單位進(jìn)行編譯。如果一個(gè)方法被頻繁調(diào)用,或方法中有效循環(huán)次數(shù)很多,將會分別觸發(fā)標(biāo)準(zhǔn)編譯和OSR(棧上替換)編譯動作。通過編譯器與解釋器恰當(dāng)?shù)貐f(xié)同工作,可以在最優(yōu)化的程序響應(yīng)時(shí)間與最佳執(zhí)行性能中取得平衡,而且無須等待本地代碼輸出才能執(zhí)行程序,即時(shí)編譯的時(shí)間壓力也相對減小,這樣有助于引入更多的代碼優(yōu)化技術(shù),輸出質(zhì)量更高的本地代碼。編譯器是把源程序的每一條語句都編譯成機(jī)器語言,并保存成二進(jìn)制文件,這樣運(yùn)行時(shí)計(jì)算機(jī)可以直接以機(jī)器語言來運(yùn)行此程序,速度很快;而解釋器則是只在執(zhí)行程序時(shí),才一條一條的解釋成機(jī)器語言給計(jì)算機(jī)來執(zhí)行,所以運(yùn)行速度是不如編譯后的程序運(yùn)行的快的.動態(tài)編譯(compile during run-time),英文稱Dynamic compilation;Just In Time也是這個(gè)意思。
HotSpot對bytecode的編譯不是在程序運(yùn)行前編譯的,而是在程序運(yùn)行過程中編譯的。
java -version
Java HotSpot(TM) Client VM (build 14.3-b01, mixed mode, sharing)
mixed mode 解釋與編譯 混合的執(zhí)行模式 默認(rèn)使用這種模式
java -Xint -version
Java HotSpot(TM) Client VM (build 14.3-b01, interPReted mode, sharing)
interpreted 純解釋模式 禁用JIT編譯
java -Xcomp -version
Java HotSpot(TM) Client VM (build 14.3-b01, compiled mode, sharing)
compiled 純編譯模式(如果方法無法編譯,則回退到解釋模式執(zhí)行無法編譯的方法)
http://blog.csdn.net/u010425776/article/details/511908012)對象的創(chuàng)建過程
當(dāng)虛擬機(jī)遇到一條含有new的指令時(shí),會進(jìn)行一系列對象創(chuàng)建的操作:
檢查常量池中是否有即將要創(chuàng)建的這個(gè)對象所屬的類的符號引用;
若常量池中沒有這個(gè)類的符號引用,說明這個(gè)類還沒有被定義!拋出ClassNotFoundException;若常量池中有這個(gè)類的符號引用,則進(jìn)行下一步工作;進(jìn)而檢查這個(gè)符號引用所代表的類是否已經(jīng)被JVM加載;
若該類還沒有被加載,就找該類的class文件,并加載進(jìn)方法區(qū);若該類已經(jīng)被JVM加載,則準(zhǔn)備為對象分配內(nèi)存;根據(jù)方法區(qū)中該類的信息確定該類所需的內(nèi)存大??; 一個(gè)對象所需的內(nèi)存大小是在這個(gè)對象所屬類被定義完就能確定的!且一個(gè)類所生產(chǎn)的所有對象的內(nèi)存大小是一樣的!JVM在一個(gè)類被加載進(jìn)方法區(qū)的時(shí)候就知道該類生產(chǎn)的每一個(gè)對象所需要的內(nèi)存大小。
從堆中劃分一塊對應(yīng)大小的內(nèi)存空間給新的對象; 分配堆中內(nèi)存有兩種方式:
指針碰撞 如果JVM的垃圾收集器采用復(fù)制算法或標(biāo)記-整理算法,那么堆中空閑內(nèi)存是完整的區(qū)域,并且空閑內(nèi)存和已使用內(nèi)存之間由一個(gè)指針標(biāo)記。那么當(dāng)為一個(gè)對象分配內(nèi)存時(shí),只需移動指針即可。因此,這種在完整空閑區(qū)域上通過移動指針來分配內(nèi)存的方式就叫做“指針碰撞”。空閑列表 如果JVM的垃圾收集器采用標(biāo)記-清除算法,那么堆中空閑區(qū)域和已使用區(qū)域交錯(cuò),因此需要用一張“空閑列表”來記錄堆中哪些區(qū)域是空閑區(qū)域,從而在創(chuàng)建對象的時(shí)候根據(jù)這張“空閑列表”找到空閑區(qū)域,并分配內(nèi)存。 綜上所述:JVM究竟采用哪種內(nèi)存分配方法,取決于它使用了何種垃圾收集器。為對象中的成員變量賦上初始值(默認(rèn)初始化);
設(shè)置對象頭中的信息;
調(diào)用對象的構(gòu)造函數(shù)進(jìn)行初始化 此時(shí),整個(gè)對象的創(chuàng)建過程就完成了。
對象的內(nèi)存模型
一個(gè)對象從邏輯角度看,它由成員變量和成員函數(shù)構(gòu)成,從物理角度來看,對象是存儲在堆中的一串二進(jìn)制數(shù),這串二進(jìn)制數(shù)的組織結(jié)構(gòu)如下。
對象在內(nèi)存中分為三個(gè)部分:
對象頭實(shí)例數(shù)據(jù)對齊補(bǔ)充1. 對象頭
對象頭中記錄了對象在運(yùn)行過程中所需要使用的一些數(shù)據(jù):哈希碼、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程ID、偏向時(shí)間戳等。
此外,對象頭中可能還包含類型指針。通過該指針能確定這個(gè)對象所屬哪個(gè)類。
此外,如果對象是一個(gè)數(shù)組,那么對象頭中還要包含數(shù)組長度。
2. 實(shí)例數(shù)據(jù)
實(shí)力數(shù)據(jù)部分就是成員變量的值,其中包含父類的成員變量和本類的成員變量。
3. 對齊補(bǔ)充
用于確保對象的總長度為8字節(jié)的整數(shù)倍。 HotSpot要求對象的總長度必須是8字節(jié)的整數(shù)倍。由于對象頭一定是8字節(jié)的整數(shù)倍,但實(shí)例數(shù)據(jù)部分的長度是任意的,因此需要對齊補(bǔ)充字段確保整個(gè)對象的總長度為8的整數(shù)倍。
訪問對象的過程
我們知道,引用類型的變量中存放的是一個(gè)地址,那么根據(jù)地址類型的不同,對象有不同的訪問方式:
句柄訪問方式 堆中需要有一塊叫做“句柄池”的內(nèi)存空間,用于存放所有對象的地址和所有對象所屬類的類信息。 引用類型的變量存放的是該對象在句柄池中的地址。訪問對象時(shí),首先需要通過引用類型的變量找到該對象的句柄,然后根據(jù)句柄中對象的地址再訪問對象。
直接指針訪問方式 引用類型的變量直接存放對象的地址,從而不需要句柄池,通過引用能夠直接訪問對象。 但對象所在的內(nèi)存空間中需要額外的策略存儲對象所屬的類信息的地址。
比較
HotSpot采用直接指針方式訪問對象,因?yàn)樗恍枰淮螌ぶ凡僮鳎瑥亩阅鼙染浔L問方式快一倍。但它需要額外的策略存儲對象在方法區(qū)中類信息的地址。
新聞熱點(diǎn)
疑難解答