階之路》第67篇:JVM面試壓軸題(2026版))
第67篇JVM面試壓軸題2026版系列導(dǎo)航《Java 100 天進(jìn)階之路》完整目錄 |?? 上一篇第66篇JIT編譯與性能優(yōu)化 |?? 下一篇第68篇JavaWeb核心技術(shù)之Servlet待發(fā)布? 本文閱讀地圖3 分鐘速覽第61~66篇完成了JVM調(diào)優(yōu)專題的全部學(xué)習(xí)本篇是JVM專題收官之作。精選 35 道大廠高頻面試題覆蓋 7 大模塊每題配標(biāo)準(zhǔn)話術(shù) 加分回答模塊核心考點(diǎn)面試權(quán)重內(nèi)存區(qū)域五大運(yùn)行時(shí)區(qū)、堆與棧區(qū)別、元空間 vs 永久代?????垃圾回收GC算法、回收器選型、G1 vs ZGC?????GC調(diào)優(yōu)調(diào)優(yōu)流程、參數(shù)配置、日志分析????類加載器雙親委派、打破雙親委派、熱部署????JIT編譯分層編譯、逃逸分析、方法內(nèi)聯(lián)???OOM排查泄漏類型、排查工具、MAT分析????調(diào)優(yōu)實(shí)戰(zhàn)參數(shù)配置、容器化JVM、生產(chǎn)問題????一、JVM內(nèi)存模型篇8題Q1JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)包含哪些區(qū)域JDK 8之后有什么變化答案五大區(qū)域——程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧、堆、方法區(qū)。JDK 8核心變化方法區(qū)實(shí)現(xiàn)從永久代PermGen改為元空間Metaspace元空間使用本地內(nèi)存而非JVM堆內(nèi)存默認(rèn)無上限受物理內(nèi)存限制永久代受-XX:MaxPermSize限制。Q2堆和棧的區(qū)別答案堆Heap——所有線程共享存儲(chǔ)對象實(shí)例和數(shù)組GC管理線程共享OutOfMemoryError。棧Stack——每個(gè)線程私有存儲(chǔ)局部變量、方法參數(shù)、對象引用自動(dòng)分配釋放線程私有StackOverflowError。Q3對象在堆內(nèi)存中的分配流程答案新對象優(yōu)先分配在Eden區(qū)Eden區(qū)滿時(shí)觸發(fā)Minor GC存活對象復(fù)制到Survivor區(qū)S0/S1每經(jīng)歷一次GC且存活年齡1年齡達(dá)到15默認(rèn)晉升到老年代大對象超過PretenureSizeThreshold直接進(jìn)入老年代。加分可通過-XX:MaxTenuringThreshold調(diào)整晉升年齡閾值。Q4String s new String(“abc”) 創(chuàng)建了幾個(gè)對象答案2個(gè)。abc字面量在字符串常量池元空間中創(chuàng)建1個(gè)對象new String()在堆中創(chuàng)建1個(gè)對象。s引用存在虛擬機(jī)棧的局部變量表中。如果池中已有abc則只創(chuàng)建1個(gè)堆對象。Q5元空間和永久代的區(qū)別答案元空間Metaspace使用本地內(nèi)存默認(rèn)無上限受物理內(nèi)存限制JDK 8使用。永久代PermGen在JVM堆內(nèi)存中受-XX:MaxPermSize限制JDK 7及之前使用。JDK 8移除永久代引入元空間字符串常量池從永久代移至堆避免永久代OOM。加分元空間默認(rèn)無上限可能導(dǎo)致本地內(nèi)存耗盡生產(chǎn)建議配置-XX:MaxMetaspaceSize。Q6程序計(jì)數(shù)器PC Register的作用為什么不會(huì)OOM答案程序計(jì)數(shù)器記錄當(dāng)前線程執(zhí)行的字節(jié)碼指令地址或行號是JVM中唯一不會(huì)拋出OutOfMemoryError的內(nèi)存區(qū)域。每個(gè)線程獨(dú)立擁有內(nèi)存極小且固定。Q7棧幀中包含哪些內(nèi)容答案棧幀包含四個(gè)部分——局部變量表方法參數(shù)和局部變量、操作數(shù)棧執(zhí)行運(yùn)算時(shí)的臨時(shí)數(shù)據(jù)、動(dòng)態(tài)鏈接將符號引用轉(zhuǎn)為直接引用支持多態(tài)、方法返回地址方法執(zhí)行完后的返回位置。Q8什么情況下會(huì)拋出StackOverflowError什么情況下會(huì)拋出OutOfMemoryError答案StackOverflowError——遞歸調(diào)用過深、方法調(diào)用層級超出棧容量-Xss可調(diào)棧大小。OutOfMemoryError: Java heap space——堆內(nèi)存耗盡-Xmx過小或內(nèi)存泄漏。OutOfMemoryError: Metaspace——元空間耗盡類加載過多或類加載器泄漏。OutOfMemoryError: unable to create new native thread——無法創(chuàng)建新線程線程數(shù)超系統(tǒng)限制。二、垃圾回收GC篇8題Q9對象如何判定為“垃圾”答案可達(dá)性分析算法——從GC Roots根對象出發(fā)向下搜索搜索路徑稱為引用鏈。不在引用鏈上的對象被判定為不可達(dá)可被回收。GC Roots包括虛擬機(jī)棧棧幀中的局部變量引用的對象、方法區(qū)中靜態(tài)屬性引用的對象、方法區(qū)中常量引用的對象、本地方法棧中JNI引用的對象。加分可達(dá)性分析需在安全點(diǎn)Safepoint執(zhí)行所有線程暫停STW。Q10四種垃圾回收算法的特點(diǎn)算法原理優(yōu)缺點(diǎn)適用區(qū)域復(fù)制算法分成兩塊存活對象復(fù)制到另一塊無碎片高效內(nèi)存利用率50%年輕代標(biāo)記-清除標(biāo)記存活對象清除未標(biāo)記無需移動(dòng)對象有碎片老年代CMS標(biāo)記-整理標(biāo)記存活對象整理到一端無碎片移動(dòng)開銷大老年代分代收集不同區(qū)域使用不同算法綜合優(yōu)勢年輕代老年代Q11Minor GC、Major GC、Full GC的區(qū)別答案Minor GC——年輕代GCEden區(qū)滿時(shí)觸發(fā)STW短暫通常10ms。Major GC——老年代GCCMS或G1的Mixed GCSTW稍長。Full GC——整個(gè)堆元空間的GCSTW最長應(yīng)盡量避免。Full GC頻繁通常意味著內(nèi)存泄漏或堆不足。Q12垃圾回收器有哪些各版本默認(rèn)是什么答案六款主要回收器——Serial單線程Client模式、Parallel多線程并行JDK 8默認(rèn)、CMS并發(fā)JDK 14已移除、G1分區(qū)化JDK 9默認(rèn)、ZGC著色指針讀屏障亞毫秒級、Shenandoah并發(fā)整理。JDK 8默認(rèn)Parallel GCJDK 9默認(rèn)G1 GC。加分ZGC在JDK 21引入分代ZGCCPU開銷降低內(nèi)存占用更小。Q13G1 GC的核心設(shè)計(jì)思想答案G1將堆劃分為多個(gè)大小相等的Region默認(rèn)2048個(gè)每個(gè)Region可扮演Eden、Survivor、Old或Humongous角色。通過Garbage-First策略優(yōu)先回收垃圾最多的Region基于歷史數(shù)據(jù)建立停頓預(yù)測模型確保GC停頓時(shí)間不超過-XX:MaxGCPauseMillis設(shè)定值。Q14CMS為什么被淘汰答案CMS的缺陷——①內(nèi)存碎片標(biāo)記-清除算法不壓縮碎片嚴(yán)重②CPU敏感并發(fā)階段占用CPU資源③并發(fā)模式失敗老年代空間不足時(shí)降級為Serial Old④浮動(dòng)垃圾并發(fā)清理時(shí)新產(chǎn)生的垃圾需下次處理。JDK 9廢棄JDK 14徹底移除。Q15ZGC為什么能實(shí)現(xiàn)亞毫秒級停頓答案ZGC利用著色指針在64位指針的高位存儲(chǔ)對象元數(shù)據(jù)配合讀屏障將大部分GC操作并發(fā)化。對象轉(zhuǎn)移時(shí)通過讀屏障攔截訪問實(shí)現(xiàn)零停頓的并發(fā)轉(zhuǎn)移。ZGC停頓時(shí)間1ms且不隨堆大小增長。Q16強(qiáng)引用、軟引用、弱引用、虛引用的區(qū)別答案強(qiáng)引用——new Object()永不回收除非不可達(dá)。軟引用——SoftReference內(nèi)存不足時(shí)回收適合緩存。弱引用——WeakReferenceGC時(shí)立即回收適合WeakHashMap、ThreadLocal。虛引用——PhantomReference無法通過它獲取對象僅用于對象回收跟蹤如Cleaner。三、GC調(diào)優(yōu)篇5題Q17GC調(diào)優(yōu)的標(biāo)準(zhǔn)流程是什么答案四步閉環(huán)——①監(jiān)控發(fā)現(xiàn)用jstat、VisualVM發(fā)現(xiàn)GC異常②分析根因分析GC日志用MAT定位內(nèi)存泄漏③參數(shù)調(diào)整每次只改1-2個(gè)參數(shù)④驗(yàn)證效果觀察GC指標(biāo)變化穩(wěn)定后固化配置。Q18G1 GC的核心調(diào)優(yōu)參數(shù)有哪些答案-XX:MaxGCPauseMillis——目標(biāo)停頓時(shí)間最核心默認(rèn)200ms調(diào)低→GC更頻繁但單次更短。-XX:G1HeapRegionSize——Region大小1-32MB大對象多可調(diào)大。-XX:InitiatingHeapOccupancyPercent——觸發(fā)Mixed GC的堆占用閾值默認(rèn)45%。-XX:G1ReservePercent——預(yù)留內(nèi)存默認(rèn)10%防止晉升失敗觸發(fā)FullGC。Q19頻繁FullGC的常見原因答案①內(nèi)存泄漏靜態(tài)集合、ThreadLocal未remove②大對象直接進(jìn)老年代PretenureSizeThreshold過小③老年代空間不足-Xmx過小④元空間不足類加載過多⑤顯式調(diào)用System.gc()-XX:DisableExplicitGC禁用。Q20吞吐量和延遲如何權(quán)衡答案吞吐量用戶代碼時(shí)間/(用戶代碼GC時(shí)間)延遲GC停頓時(shí)間。追求高吞吐→用Parallel GC適合批處理追求低延遲→用G1/ZGC適合Web/支付。兩者不可兼得。Q21容器環(huán)境JVM參數(shù)有什么特殊要求答案使用-XX:InitialRAMPercentage和-XX:MaxRAMPercentage替代固定-Xmx讓JVM感知容器內(nèi)存限制。JDK 10默認(rèn)開啟UseContainerSupport。推薦配置-XX:InitialRAMPercentage50.0 -XX:MaxRAMPercentage80.0。四、類加載器篇5題Q22雙親委派模型是什么答案類加載器收到加載請求先委派給父加載器父加載器無法加載時(shí)自己才嘗試加載。三層加載器——Bootstrap根加載器C實(shí)現(xiàn)Java中為null、Extension/Platform擴(kuò)展加載器JDK 9改名Platform、Application應(yīng)用加載器加載classpath。父加載器優(yōu)先。Q23為什么要設(shè)計(jì)雙親委派模型答案①安全避免核心類庫被篡改自定義java.lang.String不會(huì)被加載②避免重復(fù)加載確保類的唯一性③隔離性不同類加載器加載的同名類被視為不同類型。Q24如何打破雙親委派模型答案重寫loadClass()方法不先調(diào)用父加載器。典型場景——Tomcat的WebappClassLoader優(yōu)先自己加載WEB-INF/classes和WEB-INF/lib的類實(shí)現(xiàn)Web應(yīng)用隔離。JDBC驅(qū)動(dòng)加載Thread.currentThread().setContextClassLoader()也打破了雙親委派。Q25兩個(gè)類加載器加載的同一個(gè)類能互相轉(zhuǎn)換嗎答案不能。即使類名相同不同類加載器加載的類在JVM中視為不同的類型強(qiáng)轉(zhuǎn)拋ClassCastException。JVM中類唯一標(biāo)識(shí)是“類加載器全限定名”。Q26熱部署的原理是什么答案用新的類加載器重新加載目標(biāo)類替換舊的引用。舊類加載器在沒有引用后會(huì)被GC回收實(shí)現(xiàn)不停機(jī)更新。關(guān)鍵點(diǎn)①確保舊實(shí)例沒有任何引用鏈可達(dá)②新舊類不混用③通過接口調(diào)用避免類型轉(zhuǎn)換沖突。五、JIT編譯篇3題Q27什么是JIT編譯器答案JITJust-In-Time在運(yùn)行時(shí)將熱點(diǎn)字節(jié)碼編譯為本地機(jī)器碼并緩存后續(xù)直接執(zhí)行機(jī)器碼。啟動(dòng)時(shí)解釋執(zhí)行保啟動(dòng)速度運(yùn)行中JIT持續(xù)優(yōu)化熱點(diǎn)代碼。Java因此**“越跑越快”** 。Q28分層編譯的5個(gè)層級是什么答案0層解釋執(zhí)行1層C1無profile編譯2層C1有限profile編譯3層C1全量profile編譯采集運(yùn)行時(shí)數(shù)據(jù)4層C2極致優(yōu)化編譯。代碼從0層開始熱度上升后逐級晉升到4層。Q29逃逸分析能帶來哪些優(yōu)化答案逃逸分析判斷對象是否逃逸出方法或線程。基于分析結(jié)果可實(shí)現(xiàn)①棧上分配不逃逸對象在棧上減輕GC②標(biāo)量替換對象拆散為基本類型變量③鎖消除單線程鎖直接移除。六、OOM與工具篇4題Q30OOM有哪幾種常見類型答案①Java heap space——堆內(nèi)存溢出最常見內(nèi)存泄漏或-Xmx過小②Metaspace——元空間溢出類加載過多、類加載器泄漏③Direct buffer memory——直接內(nèi)存溢出NIO/Netty使用④GC overhead limit exceeded——GC回收98%內(nèi)存卻騰不出空間基本等于內(nèi)存泄漏⑤unable to create new native thread——線程數(shù)超系統(tǒng)限制。Q31生產(chǎn)環(huán)境OOM排查的標(biāo)準(zhǔn)流程答案①看日志確認(rèn)OOM類型②jstat監(jiān)控GC狀態(tài)③jmap dump生成堆快照或配置-XX:HeapDumpOnOutOfMemoryError自動(dòng)dump④MAT深度分析堆快照定位泄漏根源⑤修復(fù)代碼并驗(yàn)證。Q32常用的OOM排查工具答案jstat實(shí)時(shí)GC監(jiān)控、jmap生成堆快照會(huì)STW、MAT深度泄漏分析最專業(yè)、VisualVM可視化監(jiān)控、Arthas生產(chǎn)在線診斷阿里開源。生產(chǎn)必須開啟-XX:HeapDumpOnOutOfMemoryError自動(dòng)dump。Q33如何防止OOM發(fā)生答案①生產(chǎn)開啟-XX:HeapDumpOnOutOfMemoryError②開啟GC日志③合理設(shè)置-Xmx和-Xms④代碼避免靜態(tài)集合無限增長、資源及時(shí)關(guān)閉、ThreadLocal及時(shí)remove⑤定期壓測和review。 面試官追問陷阱加分題追問1“MAT分析堆快照時(shí)Path to GC Roots為什么要排除弱引用和軟引用” 弱引用WeakReference和軟引用SoftReference在GC時(shí)會(huì)被回收不會(huì)造成內(nèi)存泄漏。只有強(qiáng)引用鏈才是泄漏的根本原因。排除弱/軟/虛引用后留下的是真正的泄漏根源。追問2“-Xms和-Xmx設(shè)置相同有什么好處和壞處” 好處避免JVM動(dòng)態(tài)擴(kuò)容的STW開銷提高性能穩(wěn)定性。壞處啟動(dòng)時(shí)直接占用最大內(nèi)存容器環(huán)境下可能浪費(fèi)資源。生產(chǎn)通常建議設(shè)置相同如-Xms4g -Xmx4g避免擴(kuò)容帶來的性能抖動(dòng)。追問3“JDK 11的-XX:UseContainerSupport默認(rèn)開啟有什么作用” 讓JVM感知容器內(nèi)存限制使用-XX:MaxRAMPercentage代替固定-Xmx。容器內(nèi)存超限時(shí)JVM不會(huì)因超出容器限制而被K8s殺死同時(shí)避免OOM。七、練習(xí)題分析題一個(gè)服務(wù)頻繁FullGC老年代使用率持續(xù)98%FGC每小時(shí)幾百次。可能是什么原因如何排查場景題某應(yīng)用需要不停機(jī)更新代碼但每次熱部署后Metaspace持續(xù)增長最終OOM。分析原因和解決方案。代碼題寫出生產(chǎn)環(huán)境JVM參數(shù)要求堆4GB、開啟G1、目標(biāo)停頓100ms、OOM自動(dòng)dump、開啟GC日志輪轉(zhuǎn)。 你的學(xué)習(xí)進(jìn)度當(dāng)前第67篇 / 共108篇 ·進(jìn)階篇JVM調(diào)優(yōu)與故障排查第61~70篇? 已完成基礎(chǔ)篇44篇 第45~67篇 正在學(xué)第67篇? 待學(xué)習(xí)第68~108篇 完整目錄 學(xué)習(xí)指南 | 訂閱本專欄不錯(cuò)過每一篇 下一篇文章預(yù)告下一篇《第68篇JavaWeb核心技術(shù)之Servlet》內(nèi)容簡介Servlet生命周期、容器原理、Filter過濾器、Listener監(jiān)聽器、Servlet 3.0異步處理、與Spring MVC的關(guān)系。JVM調(diào)優(yōu)專題正式收官JavaWeb專題即將開啟《Java 100 天進(jìn)階之路 | 從入門到上崗就業(yè)》每天一篇建議收藏 關(guān)注一起100天拿offer 點(diǎn)擊關(guān)注我更新后第一時(shí)間收到推送