本篇內(nèi)容介紹了“Java虛擬機(jī)經(jīng)典問(wèn)題有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)公司是一家專注于成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作與策劃設(shè)計(jì),化隆網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)10余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:化隆等地區(qū)?;∽鼍W(wǎng)站價(jià)格咨詢:028-86922220Java 是如何在保證可移植性的前提下提供高執(zhí)行效率的?
Java 程序最為常見的執(zhí)行方式,是預(yù)先編譯為一種名為 Java 字節(jié)碼的中間代碼格式。這種代碼格式無(wú)法直接運(yùn)行在 CPU 之上,而是需要借助 JVM 來(lái)執(zhí)行。換句話說(shuō),只要某個(gè)平臺(tái)提供了合乎 JVM 規(guī)范的實(shí)現(xiàn),它便能執(zhí)行這份 Java 字節(jié)碼。這也就是我們經(jīng)常說(shuō)的“一次編寫,到處運(yùn)行”。
主流的 OpenJDK/OracleJDK 中所提供的 JVM 叫做 HotSpot。它同時(shí)采用了解釋執(zhí)行和即時(shí)編譯。解釋執(zhí)行就好比同聲傳譯,JVM 一邊理解輸入的字節(jié)碼一邊向 CPU 發(fā)出指令序列;即時(shí)編譯則是“磨刀不誤砍柴工”,JVM 會(huì)在運(yùn)行過(guò)程中將熱點(diǎn)代碼編譯成為可直接執(zhí)行的二進(jìn)制代碼。
這種混合執(zhí)行模式是建立在程序符合二八定律的假設(shè)上,即百分之二十的代碼占據(jù)了百分之八十的計(jì)算資源。對(duì)于不常用代碼,我們無(wú)需耗費(fèi)時(shí)間將其編譯成二進(jìn)制代碼,而是采取解釋執(zhí)行的方式運(yùn)行;另一方面,對(duì)于僅占據(jù)小部分的熱點(diǎn)代碼,JVM 則會(huì)花費(fèi)時(shí)間將其編譯為二進(jìn)制代碼,以達(dá)到理想的運(yùn)行效率。
異常捕獲是如何實(shí)現(xiàn)的?
在編譯生成的 Java 字節(jié)碼中,每個(gè)方法都附帶一個(gè)異常表。異常表中的每一行均定義了一條異常執(zhí)行路徑,其中包括規(guī)定捕獲范圍的起始字節(jié)碼索引、終止(不包含)字節(jié)碼索引,異常處理代碼的起始字節(jié)碼索引,以及所捕獲的異常類型。
當(dāng)程序觸發(fā)異常時(shí),JVM 會(huì)從上至下遍歷異常表中的所有條目。當(dāng)觸發(fā)異常的字節(jié)碼的索引值在某行異常表?xiàng)l目的捕獲范圍內(nèi),JVM 會(huì)判斷所拋出的異常和該條目想要捕獲的異常是否匹配。如果匹配,JVM 會(huì)將控制流轉(zhuǎn)移至該條目所指向的異常處理代碼。
上述異常捕獲機(jī)制還被用于 finally 從句的實(shí)現(xiàn)。通常,Java 程序的編譯器 javac 會(huì)復(fù)制多份 finally 代碼塊,放置于生成的 Java 字節(jié)碼之中,然后通過(guò)生成多行異常表?xiàng)l目,來(lái)實(shí)現(xiàn)完整的 finally 邏輯。
反射調(diào)用為什么慢?
默認(rèn)情況下,反射調(diào)用首先會(huì)被委派給 native 方法來(lái)進(jìn)行??上攵?,其運(yùn)行效率低下。當(dāng)某個(gè)反射調(diào)用的調(diào)用次數(shù)達(dá)到 15 之后,JDK 代碼斷定該調(diào)用屬于熱點(diǎn)調(diào)用。繼而,JDK 將動(dòng)態(tài)生成直接調(diào)用目標(biāo)方法的字節(jié)碼,并將反射調(diào)用的委派對(duì)象由原本的 native 方法實(shí)現(xiàn)切換至該動(dòng)態(tài)生成的實(shí)現(xiàn)。這種方式的運(yùn)行效率相對(duì)于 native 方法來(lái)說(shuō)要高很多。
之所以 JDK 不從一開始便采用動(dòng)態(tài)生成字節(jié)碼的方式,主要是因?yàn)樯蛇^(guò)程需要耗費(fèi)一定的時(shí)間。對(duì)于那些整個(gè)生命周期中僅執(zhí)行數(shù)次的反射調(diào)用,動(dòng)態(tài)生成字節(jié)碼將得不償失。
然而,即便是直接調(diào)用目標(biāo)方法的動(dòng)態(tài)實(shí)現(xiàn),其峰值性能也無(wú)法跟真正的直接調(diào)用相媲美。這背后涉及到即時(shí)編譯中的虛方法內(nèi)聯(lián)。
相關(guān)文章: < 方法內(nèi)聯(lián)(下)>
垃圾回收的基礎(chǔ)思想是什么?
目前 JVM 的主流垃圾回收器采取的都是可達(dá)性分析算法。該算法的實(shí)質(zhì)是將一系列被稱為 GC Roots 的對(duì)象作為初始的存活對(duì)象合集,然后從該合集出發(fā)探索所有能夠被該集合引用到的對(duì)象,并標(biāo)記為存活對(duì)象。當(dāng)標(biāo)記階段結(jié)束之后,未被標(biāo)記到的對(duì)象便是可以清除的。
傳統(tǒng)的垃圾回收算法在標(biāo)記、清除過(guò)程中需要中止其他應(yīng)用線程,即所謂的 Stop-The-World。新型的垃圾回收算法,如 CMS、G1 以及 ZGC,盡可能地實(shí)現(xiàn)并發(fā)標(biāo)記、清除,從而讓 Stop-The-World 的時(shí)間長(zhǎng)度可控。
垃圾回收的另一基礎(chǔ)思想則是分代回收。JVM 會(huì)將新生成的對(duì)象劃為新生代,而將在多次垃圾回收中存活下來(lái)的對(duì)象劃為老年代。JVM 會(huì)為不同的分代設(shè)置不同的回收算法,從而達(dá)到新生代多收集、快收集,老年代少收集、全收集的目標(biāo)。
如何理解 Java 內(nèi)存模型?
現(xiàn)代計(jì)算機(jī)多為對(duì)稱多處理器的體系架構(gòu)。每個(gè)處理器均有獨(dú)立的寄存器組和緩存(這在 Java 內(nèi)存模型中被抽象為工作內(nèi)存);多個(gè)處理器可同時(shí)執(zhí)行同一進(jìn)程中的不同線程。
在 Java 程序中,不同線程可能訪問(wèn)同一變量或?qū)ο蟆H绻斡删幾g器或處理器對(duì)這些訪問(wèn)進(jìn)行優(yōu)化,則很可能出現(xiàn)在單線程執(zhí)行思維下無(wú)法想象的問(wèn)題。因此,Java 語(yǔ)言規(guī)范引入了 Java 內(nèi)存模型,通過(guò)定義多項(xiàng)規(guī)則對(duì)編譯器和處理器進(jìn)行限制。
這些規(guī)則所體現(xiàn)的最為重要的屬性便是可見性,即對(duì)某一變量的訪問(wèn)能否被同一線程的其他操作,或者不同線程所觀測(cè)到。Java 內(nèi)存模型引入了多種 happens-before 關(guān)系,以實(shí)現(xiàn)上述可見性。以 volatile 字段為例,對(duì)其的寫操作 happens before 這之后的讀操作,也就是說(shuō),我們總能讀到 volatile 字段的最新值。
JVM 如何應(yīng)對(duì)對(duì)象鎖的各種場(chǎng)景?
重量級(jí)鎖是最為基礎(chǔ)、最為低效的對(duì)象鎖實(shí)現(xiàn)。JVM 會(huì)阻塞加鎖失敗的線程,并且在目標(biāo)鎖被釋放的時(shí)候,喚醒這些線程。我們用等紅燈作類比。Java 線程進(jìn)入阻塞狀態(tài)相當(dāng)于熄火停車,再次點(diǎn)火啟動(dòng)必然耗費(fèi)時(shí)間。JVM 會(huì)在進(jìn)入阻塞狀態(tài)之前進(jìn)行自旋,也就是怠速停車。如果目標(biāo)鎖能夠在短時(shí)間內(nèi)被釋放出來(lái),該線程便能夠不進(jìn)入阻塞狀態(tài),直接獲取該鎖。
重量級(jí)鎖針對(duì)的是多個(gè)線程同時(shí)競(jìng)爭(zhēng)同一把鎖的場(chǎng)景。在現(xiàn)實(shí)中,多個(gè)線程可能在不同時(shí)間段持有同一把鎖。為了應(yīng)對(duì)這種沒(méi)有鎖競(jìng)爭(zhēng)的情況,JVM 采用了輕量級(jí)鎖機(jī)制。在加鎖時(shí),JVM 將在鎖對(duì)象處做標(biāo)記,指向當(dāng)前線程的棧上;在解鎖時(shí),上述標(biāo)記會(huì)被清除。如果某線程在請(qǐng)求鎖時(shí),發(fā)現(xiàn)該鎖為輕量級(jí)鎖,并且指向另一線程所對(duì)應(yīng)的棧,那么它會(huì)將該鎖膨脹為重量級(jí)鎖。
偏向鎖所應(yīng)對(duì)的場(chǎng)景則更為樂(lè)觀:至始至終只有一個(gè)線程請(qǐng)求某把鎖。JVM 采取的做法是在第一次加鎖時(shí)為鎖對(duì)象做標(biāo)記,使其指向當(dāng)前線程的地址;在解鎖時(shí)則不做任何操作。如果下一次請(qǐng)求該鎖的仍是同一線程,便直接跳過(guò)標(biāo)記過(guò)程;否則,JVM 會(huì)將該鎖膨脹為輕量級(jí)鎖。
“Java虛擬機(jī)經(jīng)典問(wèn)題有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
標(biāo)題名稱:Java虛擬機(jī)經(jīng)典問(wèn)題有哪些-創(chuàng)新互聯(lián)
分享鏈接:http://jinyejixie.com/article14/jgcge.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、網(wǎng)站改版、App開發(fā)、企業(yè)網(wǎng)站制作、虛擬主機(jī)、微信小程序
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容