柚子快報(bào)激活碼778899分享:JVM常考八股總結(jié)
柚子快報(bào)激活碼778899分享:JVM??及斯煽偨Y(jié)
JVM是可運(yùn)行Java代碼的假想計(jì)算機(jī) ,包括一套字節(jié)碼指令集、一組寄存器、一個(gè)棧、 一個(gè)垃圾回收,堆 和 一個(gè)存儲(chǔ)方法域。JVM是運(yùn)行在操作系統(tǒng)之上的,它與硬件沒(méi)有直接 的交互。
一、JDK和JRE,JVM的區(qū)別
這篇文章講的比較清楚
二、如何理解Java是跨平臺(tái)的語(yǔ)言
Java語(yǔ)言本質(zhì)上是不能跨平臺(tái)的,真正實(shí)現(xiàn)跨平臺(tái)的是JVM,也就是Java虛擬機(jī)。寫好的Java源文件通過(guò)Javac命令編譯生成class文件(中間文件),然后JVM對(duì)class文件進(jìn)行執(zhí)行生成機(jī)器語(yǔ)言然后機(jī)器語(yǔ)言在平臺(tái)中操作,Java在不同的平臺(tái)下都有對(duì)應(yīng)的不同版本的JVM,JVM可以識(shí)別字節(jié)碼文件從而運(yùn)行。
二、JAVA運(yùn)行時(shí)數(shù)據(jù)區(qū)包括哪幾部分
PC 寄存器(PC Register),也叫程序計(jì)數(shù)器(Program Counter Register),是一塊較小的內(nèi)存空間,它的作用可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的信號(hào)指示器。JVM 棧(Java Virtual Machine Stack),與 PC 寄存器一樣,JVM 棧也是線程私有的。每一個(gè) JVM 線程都有自己的 JVM 棧(也叫方法棧),這個(gè)棧與線程同時(shí)創(chuàng)建,它的生命周期與線程相同。本地方法棧(Native Method Stack),JVM 可能會(huì)使用到傳統(tǒng)的棧來(lái)支持?Native 方法open in new window的執(zhí)行,這個(gè)棧就是本地方法棧。堆(Heap),在 JVM 中,堆是可供各條線程共享的運(yùn)行時(shí)內(nèi)存區(qū)域,也是供所有類實(shí)例和數(shù)據(jù)對(duì)象分配內(nèi)存的區(qū)域。方法區(qū)(Method area),JDK 8 開(kāi)始,使用元空間取代了永久代。方法區(qū)是 JVM 中的一個(gè)邏輯區(qū)域,用于存儲(chǔ)類的結(jié)構(gòu)信息,包括類的定義、方法的定義、字段的定義以及字節(jié)碼指令。不同的是,元空間不再是 JVM 內(nèi)存的一部分,而是通過(guò)本地內(nèi)存(Native Memory)來(lái)實(shí)現(xiàn)的。運(yùn)行時(shí)常量池open in new window,運(yùn)行時(shí)常量池是每一個(gè)類或接口的常量在運(yùn)行時(shí)的表現(xiàn)形式,它包括了編譯器可知的數(shù)值字面量,以及運(yùn)行期解析后才能獲得的方法或字段的引用。簡(jiǎn)而言之,當(dāng)一個(gè)方法或者變量被引用時(shí),JVM 通過(guò)運(yùn)行時(shí)常量區(qū)來(lái)查找方法或者變量在內(nèi)存里的實(shí)際地址。
其中 PC 寄存器、虛擬機(jī)棧以及本地方法棧屬于線程私有的,堆以及元空間(方法區(qū)的實(shí)現(xiàn))屬于共享數(shù)據(jù)區(qū),不同的線程共享這兩部分內(nèi)存數(shù)據(jù)。
三、java和C++比速度
為了優(yōu)化 Java 的性能 ,JVM 在解釋器之外引入了 JIT 編譯器:當(dāng)程序運(yùn)行時(shí),解釋器首先發(fā)揮作用,代碼可以直接執(zhí)行。隨著時(shí)間推移,即時(shí)編譯器逐漸發(fā)揮作用,把越來(lái)越多的代碼編譯優(yōu)化成本地代碼,來(lái)獲取更高的執(zhí)行效率。解釋器這時(shí)可以作為編譯運(yùn)行的降級(jí)手段,在一些不可靠的編譯優(yōu)化出現(xiàn)問(wèn)題時(shí),再切換回解釋執(zhí)行,保證程序可以正常運(yùn)行。
逃逸分析(Escape Analysis)是一種編譯器優(yōu)化技術(shù),用于判斷對(duì)象的作用域和生命周期。如果編譯器確定一個(gè)對(duì)象不會(huì)逃逸出方法或線程的范圍,它可以選擇在棧上分配這個(gè)對(duì)象,而不是在堆上。這樣做可以減少垃圾回收的壓力,并提高性能。
四、虛擬機(jī)棧幀包括哪些
五、字節(jié)碼文件有哪些部分組成
六、常量池中有哪些信息
字面量
字面量就是指由字母、數(shù)字等構(gòu)成的字符串或者數(shù)值常量。
字面量只可以右值出現(xiàn),所謂右值是指等號(hào)右邊的值
如:int a=1 這里的a為左值,1為右值。在這個(gè)例子中1就是字面量。
符號(hào)引用
符號(hào)引用是編譯原理中的概念,是相對(duì)于直接引用來(lái)說(shuō)的。主要包括了以下三類常量:
類和接口的全限定名? 字段的名稱和描述符? 方法的名稱和描述符
類加載器將字節(jié)碼的信息寫入到方法區(qū)中(1.8后叫做永久代),通過(guò)堆區(qū)有個(gè)lang對(duì)象訪問(wèn)這個(gè)Kclass
七、類的生命周期
類的初始化階段是執(zhí)行靜態(tài)代碼塊(clinit方法),并為靜態(tài)變量賦值。
八、類加載器的分類
九、GC Roots?到底是什么東西呢,哪些對(duì)象可以作為 GC Root 呢?
虛擬機(jī)棧(棧幀中的本地變量表)中引用的對(duì)象 本地方法棧中 JNI(即一般說(shuō)的 Native 方法)引用的對(duì)象 方法區(qū)中類靜態(tài)屬性引用的對(duì)象 方法區(qū)中常量引用的對(duì)象
十、垃圾收集算法
標(biāo)記清除算法
賦值算法
標(biāo)記整理算法
分代收集算法
新生代和老年代
十一、垃圾收集器
1、CMS
CMS 垃圾收集器通過(guò)三色標(biāo)記算法,實(shí)現(xiàn)了垃圾回收線程與用戶線程的并發(fā)執(zhí)行,從而極大地降低了系統(tǒng)響應(yīng)時(shí)間,提高了強(qiáng)交互應(yīng)用程序的體驗(yàn)。它的運(yùn)行過(guò)程分為 4 個(gè)步驟,包括:
初始標(biāo)記并發(fā)標(biāo)記重新標(biāo)記并發(fā)清除
初始標(biāo)記,指的是尋找所有被 GCRoots 引用的對(duì)象,該階段需要「Stop the World」。這個(gè)步驟僅僅只是標(biāo)記一下 GC Roots 能直接關(guān)聯(lián)到的對(duì)象,并不需要做整個(gè)引用的掃描,因此速度很快。
并發(fā)標(biāo)記,指的是對(duì)「初始標(biāo)記階段」標(biāo)記的對(duì)象進(jìn)行整個(gè)引用鏈的掃描,該階段不需要「Stop the World」。 對(duì)整個(gè)引用鏈做掃描需要花費(fèi)非常多的時(shí)間,因此通過(guò)垃圾回收線程與用戶線程并發(fā)執(zhí)行,可以降低垃圾回收的時(shí)間。
這也是 CMS 能極大降低 GC 停頓時(shí)間的核心原因,但這也帶來(lái)了一些問(wèn)題,即:并發(fā)標(biāo)記的時(shí)候,引用可能發(fā)生變化,因此可能發(fā)生漏標(biāo)(本應(yīng)該回收的垃圾沒(méi)有被回收)和多標(biāo)(本不應(yīng)該回收的垃圾被回收)了。
重新標(biāo)記,指的是對(duì)「并發(fā)標(biāo)記」階段出現(xiàn)的問(wèn)題進(jìn)行校正,該階段需要「Stop the World」。正如并發(fā)標(biāo)記階段說(shuō)到的,由于垃圾回收算法和用戶線程并發(fā)執(zhí)行,雖然能降低響應(yīng)時(shí)間,但是會(huì)發(fā)生漏標(biāo)和多標(biāo)的問(wèn)題。所以對(duì)于 CMS 來(lái)說(shuō),它需要在這個(gè)階段做一些校驗(yàn),解決并發(fā)標(biāo)記階段發(fā)生的問(wèn)題。
并發(fā)清除,指的是將標(biāo)記為垃圾的對(duì)象進(jìn)行清除,該階段不需要「Stop the World」。 在這個(gè)階段,垃圾回收線程與用戶線程可以并發(fā)執(zhí)行,因此并不影響用戶的響應(yīng)時(shí)間。
CMS 的優(yōu)點(diǎn)是:并發(fā)收集、低停頓。但缺點(diǎn)也很明顯:
①、對(duì) CPU 資源非常敏感,因此在 CPU 資源緊張的情況下,CMS 的性能會(huì)大打折扣。
默認(rèn)情況下,CMS 啟用的垃圾回收線程數(shù)是(CPU數(shù)量 + 3)/4,當(dāng) CPU 數(shù)量很大時(shí),啟用的垃圾回收線程數(shù)占比就越小。但如果 CPU 數(shù)量很小,例如只有 2 個(gè) CPU,垃圾回收線程占用就達(dá)到了 50%,這極大地降低系統(tǒng)的吞吐量,無(wú)法接受。
②、CMS 采用的是「標(biāo)記-清除」算法,會(huì)產(chǎn)生大量的內(nèi)存碎片,導(dǎo)致空間不連續(xù),當(dāng)出現(xiàn)大對(duì)象無(wú)法找到連續(xù)的內(nèi)存空間時(shí),就會(huì)觸發(fā)一次 Full GC,這會(huì)導(dǎo)致系統(tǒng)的停頓時(shí)間變長(zhǎng)。
③、CMS 無(wú)法處理浮動(dòng)垃圾,當(dāng) CMS 在進(jìn)行垃圾回收的時(shí)候,應(yīng)用程序還在不斷地產(chǎn)生垃圾,這些垃圾會(huì)在 CMS 垃圾回收結(jié)束之后產(chǎn)生,這些垃圾就是浮動(dòng)垃圾,CMS 無(wú)法處理這些浮動(dòng)垃圾,只能在下一次 GC 時(shí)清理掉。
G1
G1 有專門分配大對(duì)象的 Region 叫 Humongous 區(qū),而不是讓大對(duì)象直接進(jìn)入老年代的 Region 中。在 G1 中,大對(duì)象的判定規(guī)則就是一個(gè)大對(duì)象超過(guò)了一個(gè) Region 大小的 50%,比如每個(gè) Region 是 2M,只要一個(gè)對(duì)象超過(guò)了 1M,就會(huì)被放入 Humongous 中,而且一個(gè)大對(duì)象如果太大,可能會(huì)橫跨多個(gè) Region 來(lái)存放。
G1 會(huì)根據(jù)各個(gè)區(qū)域的垃圾回收情況來(lái)決定下一次垃圾回收的區(qū)域,這樣就避免了對(duì)整個(gè)堆內(nèi)存進(jìn)行垃圾回收,從而降低了垃圾回收的時(shí)間。
②、增量:G1 可以以增量方式執(zhí)行垃圾回收,這意味著它不需要一次性回收整個(gè)堆空間,而是可以逐步、增量地清理。有助于控制停頓時(shí)間,尤其是在處理大型堆時(shí)。
③、并行:G1 垃圾回收器可以并行回收垃圾,這意味著它可以利用多個(gè) CPU 來(lái)加速垃圾回收的速度,這一特性在年輕代的垃圾回收(Minor GC)中特別明顯,因?yàn)槟贻p代的回收通常涉及較多的對(duì)象和較高的回收速率。
④、標(biāo)記整理:在進(jìn)行老年代的垃圾回收時(shí),G1 使用標(biāo)記-整理算法。這個(gè)過(guò)程分為兩個(gè)階段:標(biāo)記存活的對(duì)象和整理(壓縮)堆空間。通過(guò)整理,G1 能夠避免內(nèi)存碎片化,提高內(nèi)存利用率。
年輕代的垃圾回收(Minor GC)使用復(fù)制算法,因?yàn)槟贻p代的對(duì)象通常是朝生夕死的。
⑤、STW:G1 也是基于「標(biāo)記-清除」算法,因此在進(jìn)行垃圾回收的時(shí)候,仍然需要「Stop the World」。不過(guò),G1 在停頓時(shí)間上添加了預(yù)測(cè)機(jī)制,用戶可以指定期望停頓時(shí)間。
G1 中存在三種 GC 模式,分別是 Young GC、Mixed GC 和 Full GC。
當(dāng) Eden 區(qū)的內(nèi)存空間無(wú)法支持新對(duì)象的內(nèi)存分配時(shí),G1 會(huì)觸發(fā) Young GC。
當(dāng)需要分配對(duì)象到 Humongous 區(qū)域或者堆內(nèi)存的空間占比超過(guò)?-XX:G1HeapWastePercent?設(shè)置的 InitiatingHeapOccupancyPercent 值時(shí),G1 會(huì)觸發(fā)一次 concurrent marking,它的作用就是計(jì)算老年代中有多少空間需要被回收,當(dāng)發(fā)現(xiàn)垃圾的占比達(dá)到?-XX:G1HeapWastePercent?中所設(shè)置的 G1HeapWastePercent 比例時(shí),在下次 Young GC 后會(huì)觸發(fā)一次 Mixed GC。
Mixed GC 是指回收年輕代的 Region 以及一部分老年代中的 Region。Mixed GC 和 Young GC 一樣,采用的也是復(fù)制算法。
在 Mixed GC 過(guò)程中,如果發(fā)現(xiàn)老年代空間還是不足,此時(shí)如果 G1HeapWastePercent 設(shè)定過(guò)低,可能引發(fā) Full GC。-XX:G1HeapWastePercent?默認(rèn)是 5,意味著只有 5% 的堆是“浪費(fèi)”的。如果浪費(fèi)的堆的百分比大于 G1HeapWastePercent,則運(yùn)行 Full GC。
在以 Region 為最小管理單元以及所采用的 GC 模式的基礎(chǔ)上,G1 建立了停頓預(yù)測(cè)模型,即 Pause Prediction Model 。這也是 G1 非常被人所稱道的特性。
我們可以借助?-XX:MaxGCPauseMillis?來(lái)設(shè)置期望的停頓時(shí)間(默認(rèn) 200ms),G1 會(huì)根據(jù)這個(gè)值來(lái)計(jì)算出一個(gè)合理的 Young GC 的回收時(shí)間,然后根據(jù)這個(gè)時(shí)間來(lái)制定 Young GC 的回收計(jì)劃。
十二、類加載器包括哪些什么是雙親委派?
雙親委派模型的工作過(guò)程如下:如果一個(gè)類加載器收到了類加載的請(qǐng)求,它首先不會(huì)自己去嘗試加載這個(gè)類,而是把這個(gè)請(qǐng)求委派給父類加載器去完成,每一層的類加載器都是如此,因此所有的加載請(qǐng)求最終都應(yīng)該傳送到最頂層的啟動(dòng)類加載器,只有當(dāng)父加載器反饋?zhàn)约簾o(wú)法完成這個(gè)加載請(qǐng)求(它的搜索范圍中沒(méi)有找到所需的類)時(shí),子加載器才會(huì)嘗試自己去完成加載。
即時(shí)編譯器的分層編譯
要編譯出優(yōu)化程度越高的代碼通常都需要越長(zhǎng)的編譯時(shí)間,為了在程序啟動(dòng)速度與運(yùn)行效率之間達(dá)到最佳平衡,HotSpot 在編譯子系統(tǒng)中加入了分層編譯(Tiered Compilation):
第 0 層:程序純解釋執(zhí)行,并且解釋器不開(kāi)啟性能監(jiān)控功能;第 1 層:使用客戶端編譯器將字節(jié)碼編譯為本地代碼來(lái)運(yùn)行,進(jìn)行簡(jiǎn)單可靠的穩(wěn)定優(yōu)化,不開(kāi)啟性能監(jiān)控功能;第 2 層:仍然使用客戶端編譯執(zhí)行,僅開(kāi)啟方法及回邊次數(shù)統(tǒng)計(jì)等有限的性能監(jiān)控;第 3 層:仍然使用客戶端編譯執(zhí)行,開(kāi)啟全部性能監(jiān)控;第 4 層:使用服務(wù)端編譯器將字節(jié)碼編譯為本地代碼,其耗時(shí)更長(zhǎng),并且會(huì)根據(jù)性能監(jiān)控信息進(jìn)行一些不可靠的激進(jìn)優(yōu)化。
十三、方法內(nèi)聯(lián)
最重要的優(yōu)化手段,它會(huì)將目標(biāo)方法中的代碼原封不動(dòng)地 “復(fù)制” 到發(fā)起調(diào)用的方法之中,避免發(fā)生真實(shí)的方法調(diào)用,并采用名為類型繼承關(guān)系分析(Class Hierarchy Analysis,CHA)的技術(shù)來(lái)解決虛方法(Java 語(yǔ)言中默認(rèn)的實(shí)例方法都是虛方法)的內(nèi)聯(lián)問(wèn)題。
?十四、逃逸分析
逃逸行為主要分為以下兩類:
方法逃逸:當(dāng)一個(gè)對(duì)象在方法里面被定義后,它可能被外部方法所引用,例如作為調(diào)用參數(shù)傳遞到其他方法中,此時(shí)稱為方法逃逸;線程逃逸:當(dāng)一個(gè)對(duì)象在方法里面被定義后,它可能被外部線程所訪問(wèn),例如賦值給可以在其他線程中訪問(wèn)的實(shí)例變量,此時(shí)稱為線程逃逸,其逃逸程度高于方法逃逸。 如果能證明一個(gè)對(duì)象不會(huì)逃逸到方法或線程之外,或者逃逸程度比較低(只逃逸出方法而不會(huì)逃逸出線程),則可以對(duì)這個(gè)對(duì)象實(shí)例采取不同程序的優(yōu)化: 棧上分配 (Stack Allocations)?:如果一個(gè)對(duì)象不會(huì)逃逸到線程外,那么將會(huì)在棧上分配內(nèi)存來(lái)創(chuàng)建這個(gè)對(duì)象,而不是 Java 堆上,此時(shí)對(duì)象所占用的內(nèi)存空間就會(huì)隨著棧幀的出棧而銷毀,從而可以減輕垃圾回收的壓力。標(biāo)量替換 (Scalar Replacement)?:如果一個(gè)數(shù)據(jù)已經(jīng)無(wú)法再分解成為更小的數(shù)據(jù)類型,那么這些數(shù)據(jù)就稱為標(biāo)量(如 int、long 等數(shù)值類型及 reference 類型等);反之,如果一個(gè)數(shù)據(jù)可以繼續(xù)分解,那它就被稱為聚合量(如對(duì)象)。如果一個(gè)對(duì)象不會(huì)逃逸外方法外,那么就可以將其改為直接創(chuàng)建若干個(gè)被這個(gè)方法使用的成員變量來(lái)替代,從而減少內(nèi)存占用。同步消除 (Synchronization Elimination)?:如果一個(gè)變量不會(huì)逃逸出線程,那么對(duì)這個(gè)變量實(shí)施的同步措施就可以消除掉。
十五、內(nèi)存泄漏
內(nèi)存泄漏通常是指堆內(nèi)存,通常是指一些大對(duì)象不被回收的情況 1 、通過(guò) jmap 或設(shè)置 jvm 參數(shù)獲取堆內(nèi)存快照 dump 2 、通過(guò)工具, VisualVM 去分析 dump 文件, VisualVM 可以加載離線的 dump 文件
3 、通過(guò)查看堆信息的情況,可以大概定位內(nèi)存溢出是哪行代碼出了問(wèn)題 4 、找到對(duì)應(yīng)的代碼,通過(guò)閱讀上下文的情況,進(jìn)行修復(fù)即可
十六、cpu百分百如和檢查
1. 使用 top 命令查看占用 cpu 的情況 2. 通過(guò) top 命令查看后,可以查看是哪一個(gè)進(jìn)程占用 cpu 較高 3. 使用 ps 命令查看進(jìn)程中的線程信息ps H -eo pid,tid,%cpu | grep 40940 4. 使用 jstack 命令查看進(jìn)程中哪些線程出現(xiàn)了問(wèn)題,最終定位問(wèn)題
柚子快報(bào)激活碼778899分享:JVM常考八股總結(jié)
好文推薦
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。