1. 程式人生 > >JVM相關面試題及答案

JVM相關面試題及答案

1、你知道哪些或者你們線上使⽤什麼GC策略?它有什麼優勢,適⽤於什麼場景?

參考 觸發JVM進行Full GC的情況及應對策略

2、Java類載入器包括⼏種?它們之間的⽗⼦關係是怎麼樣的?雙親委派機制是什麼意思?有什麼好處?

啟動Bootstrap類載入、擴充套件Extension類載入、系統System類載入。

父子關係如下:

  • 啟動類載入器 ,由C++ 實現,沒有父類;
  • 擴充套件類載入器,由Java語言實現,父類載入器為null;
  • 系統類載入器,由Java語言實現,父類載入器為擴充套件類載入器;
  • 自定義類載入器,父類載入器肯定為AppClassLoader。

雙親委派機制:類載入器收到類載入請求,自己不載入,向上委託給父類載入,父類載入不了,再自己載入。
優勢避免Java核心API篡改。詳細檢視:深入理解Java類載入器(ClassLoader)

3、如何⾃定義⼀個類載入器?你使⽤過哪些或者你在什麼場景下需要⼀個⾃定義的類載入器嗎?

自定義類載入的意義:

  1. 載入特定路徑的class檔案
  2. 載入一個加密的網路class檔案
  3. 熱部署載入class檔案

4、堆記憶體設定的引數是什麼?

  • -Xmx 設定堆的最大空間大小
  • -Xms 設定堆的最小空間大小

5、Perm Space中儲存什麼資料?會引起OutOfMemory嗎?

載入class檔案。

會引起,出現異常可以設定 -XX:PermSize 的大小。JDK 1.8後,字串常量不存放在永久帶,而是在堆記憶體中,JDK8以後沒有永久代概念,而是用元空間替代,元空間不存在虛擬機器中,二是使用本地記憶體。

詳細檢視Java8記憶體模型—永久代(PermGen)和元空間(Metaspace)

6、做GC時,⼀個物件在記憶體各個Space中被移動的順序是什麼?

標記清除法,複製演算法,標記整理、分代演算法。

新生代一般採用複製演算法 GC,老年代使用標記整理演算法。
垃圾收集器:序列新生代收集器、序列老生代收集器、並行新生代收集器、並行老年代收集器。
CMS(Current Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器,它是一種併發收集器,採用的是Mark-Sweep演算法。

詳見 Java GC機制

7、你有沒有遇到過OutOfMemory問題?你是怎麼來處理這個問題的?處理 過程中有哪些收穫?

permgen space、heap space 錯誤。

常見的原因

  • 記憶體載入的資料量太大:一次性從資料庫取太多資料;
  • 集合類中有對物件的引用,使用後未清空,GC不能進行回收;
  • 程式碼中存在迴圈產生過多的重複物件;
  • 啟動引數堆記憶體值小。

詳見 Java 記憶體溢位(java.lang.OutOfMemoryError)的常見情況和處理方式總結

8、JDK 1.8之後Perm Space有哪些變動? MetaSpace⼤⼩預設是⽆限的麼? 還是你們會通過什麼⽅式來指定⼤⼩?

JDK 1.8後用元空間替代了 Perm Space;字串常量存放到堆記憶體中。

MetaSpace大小預設沒有限制,一般根據系統記憶體的大小。JVM會動態改變此值。

  • -XX:MetaspaceSize:分配給類元資料空間(以位元組計)的初始大小(Oracle邏輯儲存上的初始高水位,the initial high-water-mark)。此值為估計值,MetaspaceSize的值設定的過大會延長垃圾回收時間。垃圾回收過後,引起下一次垃圾回收的類元資料空間的大小可能會變大。
  • -XX:MaxMetaspaceSize:分配給類元資料空間的最大值,超過此值就會觸發Full GC,此值預設沒有限制,但應取決於系統記憶體的大小。JVM會動態地改變此值。

9、jstack 是⼲什麼的? jstat 呢?如果線上程式週期性地出現卡頓,你懷疑可 能是 GC 導致的,你會怎麼來排查這個問題?執行緒⽇志⼀般你會看其中的什麼 部分?

jstack 用來查詢 Java 程序的堆疊資訊。

jvisualvm 監控記憶體洩露,跟蹤垃圾回收、執行時記憶體、cpu分析、執行緒分析。

詳見Java jvisualvm簡要說明,可參考 線上FullGC頻繁的排查

10、StackOverflow異常有沒有遇到過?⼀般你猜測會在什麼情況下被觸發?如何指定⼀個執行緒的堆疊⼤⼩?⼀般你們寫多少?

棧記憶體溢位,一般由棧記憶體的區域性變數過爆了,導致記憶體溢位。出現在遞迴方法,引數個數過多,遞迴過深,遞迴沒有出口。

原文:http://www.importnew.com/29299.html

 

 

1. 類的例項化順序,比如父類靜態資料,建構函式,欄位,子類靜態資料,建構函式,欄位,他們的執行順序

答:先靜態、先父後子。 
先靜態:父靜態 > 子靜態 
優先順序:父類 > 子類 靜態程式碼塊 > 非靜態程式碼塊 > 建構函式 
一個類的例項化過程: 
1,父類中的static程式碼塊,當前類的static 
2,順序執行父類的普通程式碼塊 
3,父類的建構函式 
4,子類普通程式碼塊 
5,子類(當前類)的建構函式,按順序執行。 
6,子類方法的執行,

2. JVM記憶體分配

3. Java 8的記憶體分代改進

從永久代到元空間,在小範圍自動擴充套件永生代避免溢位

4. JVM垃圾回收機制,何時觸發MinorGC等操作

分代垃圾回收機制:不同的物件生命週期不同。把不同生命週期的物件放在不同代上,不同代上採用最合適它的垃圾回收方式進行回收。 
JVM中共劃分為三個代:年輕代、年老代和持久代, 
年輕代:存放所有新生成的物件; 
年老代:在年輕代中經歷了N次垃圾回收仍然存活的物件,將被放到年老代中,故都是一些生命週期較長的物件; 
持久代:用於存放靜態檔案,如Java類、方法等。 
新生代的垃圾收集器命名為“minor gc”,老生代的GC命名為”Full Gc 或者Major GC”.其中用System.gc()強制執行的是Full Gc. 
判斷物件是否需要回收的方法有兩種: 
1.引用計數 
當某物件的引用數為0時,便可以進行垃圾收集。 
2.物件引用遍歷 
果某物件不能從這些根物件的一個(至少一個)到達,則將它作為垃圾收集。在物件遍歷階段,gc必須記住哪些物件可以到達,以便刪除不可到達的物件,這稱為標記(marking)物件。

觸發GC(Garbage Collector)的條件: 
1)GC在優先順序最低的執行緒中執行,一般在應用程式空閒即沒有應用執行緒在執行時被呼叫。 
2)Java堆記憶體不足時,GC會被呼叫。

5. jvm中一次完整的GC流程(從ygc到fgc)是怎樣的,重點講講物件如何晉升到老年代等

答:物件優先在新生代區中分配,若沒有足夠空間,Minor GC; 
大物件(需要大量連續記憶體空間)直接進入老年態;長期存活的物件進入老年態。如果物件在新生代出生並經過第一次MGC後仍然存活,年齡+1,若年齡超過一定限制(15),則被晉升到老年態。

6. 你知道哪幾種垃圾收集器,各自的優缺點,重點講下cms,g1

7. Eden和Survivor的比例分配等

預設比例8:1。 
大部分物件都是朝生夕死。 
複製演算法的基本思想就是將記憶體分為兩塊,每次只用其中一塊,當這一塊記憶體用完,就將還活著的物件複製到另外一塊上面。複製演算法不會產生記憶體碎片。 
8. 深入分析了Classloader,雙親委派機制 
ClassLoader:類載入器(class loader)用來載入 Java 類到 Java 虛擬機器中。Java 源程式(.java 檔案)在經過 Java 編譯器編譯之後就被轉換成 Java 位元組程式碼(.class 檔案)。類載入器負責讀取 Java 位元組程式碼,並轉換成 java.lang.Class 類的一個例項。 
雙親委派機制:某個特定的類載入器在接到載入類的請求時,首先將載入任務委託給父類載入器,依次遞迴,如果父類載入器可以完成類載入任務,就成功返回;只有父類載入器無法完成此載入任務時,才自己去載入。

9. JVM的編譯優化

10. 對Java記憶體模型的理解,以及其在併發中的應用

Java記憶體模型的主要目標: 定義程式中各個變數的訪問規則。 
Java執行緒之間的通訊由Java記憶體模型(本文簡稱為JMM)控制。 
所有變數的儲存都在主記憶體,每條執行緒還都有自己的工作記憶體,執行緒的工作記憶體中儲存了被該執行緒使用到的變數的主記憶體副本拷貝,執行緒對變數的所有操作必須在工作記憶體完成,而不能直接讀取主記憶體中的變數。不同的執行緒直接無法訪問對方工作記憶體中的變數,執行緒間變數的傳遞均需要通過主記憶體來完成。 


執行緒間通訊: 
1. 首先,執行緒A把本地記憶體A中更新過的共享變數重新整理到主記憶體中去。 
2. 然後,執行緒B到主記憶體中去讀取執行緒A之前已更新過的共享變數。

11. 指令重排序,記憶體柵欄等

指令重排序:編譯器或執行時環境為了優化程式效能而採取的對指令進行重新排序執行的一種手段。在單執行緒程式中,對存在控制依賴的操作重排序,不會改變執行結果;但在多執行緒程式中,對存在控制依賴的操作重排序,可能會改變程式的執行結果。

12. OOM錯誤,stackoverflow錯誤,permgen space錯誤

13. JVM常用引數

JVM主要引數:堆設定、回收器選擇(序列、並行、併發收集器)

14. tomcat結構,類載入器流程 
 
目錄結構: 
• /bin:存放windows或Linux平臺上啟動和關閉Tomcat的指令碼檔案 
• /conf:存放Tomcat伺服器的各種全域性配置檔案,其中最重要的是server.xml和web.xml 
• /doc:存放Tomcat文件 
• /server:包含三個子目錄:classes、lib和webapps 
• /server/lib:存放Tomcat伺服器所需的各種JAR檔案 
• /server/webapps:存放Tomcat自帶的兩個WEB應用admin應用和 manager應用 
• /common/lib:存放Tomcat伺服器以及所有web應用都可以訪問的jar檔案 
• /shared/lib:存放所有web應用都可以訪問的jar檔案(但是不能被Tomcat伺服器訪問) 
• /logs:存放Tomcat執行時的日誌檔案 
• /src:存放Tomcat的原始碼 
• /webapps:Tomcat的主要Web釋出目錄,預設情況下把Web應用檔案放於此目錄 
• /work:存放JSP編譯後產生的class檔案

類載入器模式,雙親委派模式: 


15. volatile的語義,它修飾的變數一定執行緒安全嗎

一個變數被定義為volatile之後,具備兩重語義:①保證此變數對所有執行緒的可見性,即當一條執行緒修改了這個值,新值對於其他所有執行緒來說是立即得知的,普通變數需要通過主記憶體傳遞。②禁止指令重排序優化。 
Volatile修飾的變數不一定是執行緒安全的,eg非原子操作a++等

16. g1和cms區別,吞吐量優先和響應優先的垃圾收集器選擇

CMS收集器:一款以獲取最短回收停頓時間為目標的收集器,是基於“標記-清除”演算法實現的,分為4個步驟:初始標記、併發標記、重新標記、併發清除。 
G1收集器:面向服務端應用的垃圾收集器,過程:初始標記;併發標記;最終標記;篩選回收。整體上看是“標記-整理”,區域性看是“複製”,不會產生記憶體碎片。 
吞吐量優先的並行收集器:以到達一定的吞吐量為目標,適用於科學技術和後臺處理等。 
響應時間優先的併發收集器:保證系統的響應時間,減少垃圾收集時的停頓時間。適用於應用伺服器、電信領域等。

17. 說一說你對環境變數classpath的理解?如果一個類不在classpath下,為什麼會丟擲ClassNotFoundException異常,如果在不改變這個類路徑的前期下,怎樣才能正確載入這個類?

classpath是javac編譯器的一個環境變數。它的作用與import、package關鍵字有關。package的所在位置,就是設定CLASSPATH當編譯器面對import packag這個語句時,它先會查詢CLASSPATH所指定的目錄,並檢視子目錄java/util是否存在,然後找出名稱吻合的已編譯檔案(.class檔案)。如果沒有找到就會報錯! 
動態載入包

18. 說一下強引用、軟引用、弱引用、虛引用以及他們之間和gc的關係

強引用:new出的物件之類的引用, 
只要強引用還在,永遠不會回收 
軟引用:引用但非必須的物件,記憶體溢位異常之前,回收 
弱引用:非必須的物件,物件能生存到下一次垃圾收集發生之前。 
虛引用:對生存時間無影響,在垃圾回收時得到通知。
--------------------- 
作者:zhaomaoer  
原文:https://blog.csdn.net/zd836614437/article/details/64126826