JVM面試
JVM:Java Virtual Machine
在面試中會JVM是經常被問的,關於JVM的常問問題一般有:
- JVM的內存結構;
- 常用參數;
- 垃圾回收機制以及算法以及各個算法的對比
- JVM調優
以上四個問題佔了80%,都回答出來已經差不多了。
在這裏我自己使用的都是JDK1.8。
切記:JVM不同的版本,它的差別是非常大的。以8爲主,跟7對比,跟9對比。面試的時候先說你的版本是什麼。
官方文檔:https://docs.oracle.com/javase/8/docs/(文檔比較亂,需要仔細找)
比如查看jps命令的使用:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jps.html
再比如查看jinfo的使用(也可以–help查看)
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jinfo.html
其中有篇文章一定要看的:
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/index.html
爲什麼講JVM?
1)面試必備 大數據,Hadoop/storm等都是運行在JVM之上的,Spark也是;
2)性能調優 工作中,是非常重要的,調好的話性能提升非常大,不同的版本參數不一樣,當版本發生變化時,要調很多參數。比如,版本發生變化時,不修改,可能導致spark代碼提交的時候會非常慢,網頁上看的時候GC時間特別長
參數舉例:Hadoop裏面設置JVM堆的大小的參數是什麼?hadoop-env.sh裏面的export HADOOP_HEAPSIZE=(默認1000M,有時候需要調整的)
某臺機器上面作業跑的非常慢,負載非常高?Linux命令用top看的時候,有個參數load average:後面三個參數。Load Average 就是一段時間 (1 分鐘、5分鐘、15分鐘) 內平均 Load 。
有時候負載很高,有時候cpu飆得很高,memory爆掉了等等,那怎麼辦?
3)性能監控/調整
舉個例子,當一個作業跑着的時候突然卡死,或者變慢,你的代碼裏面的log4j沒打日誌,讓你去定位代碼裏面哪個方法裏面的哪個變量出現了問題,是很難定位的。線上服務不能重啓的,重啓的話肯定會影響整個LSA的。那麼有沒有辦法去直接去調整運行中代碼的字節碼(.class文件),字節碼是跑在JVM裏面的。那麼直接通過JVM把裏面相關的東西給修改掉,這樣的話就不需要重啓,這樣就可以非常方便的定位哪個方法裏的哪個變量出現了問題。
JVM參數
比如jinfo、jstat、jmap等
JVM裏的參數類型
1)標準參數
什麼叫標準參數,舉個例子:java -version 或者java -help會出現很多參數,這些參數是不會變的。標準參數和這些類似。
2)X參數
可能會變,但是變得又不多,比如:
從上面可以看到加上-X有很多模式,解釋模式去執行你的代碼,編譯模式去執行你的代碼,混合模式去執行你的代碼(這件事情是解釋還是編譯交由JVM來處理)。
那麼Java是解釋執行的還是編譯執行的?不能確定,因爲有個mixed混合執行。
3)XX參數
舉例:標準寫法
-XX:[±]UseG1GC :表示把UseG1GC這個參數給啓用或者禁用
還有一些參數是這樣寫:
-XX:MaxPermSize=64m :表示把MaxPermSize這個參數設置成64M
-Xmx 、-Xms、-Xss這三個參數是屬於XX參數類型裏面的。
其中-Xms 就相當於 -XX:InitalHeapSize(JVM初始化堆大小)
-Xmx 就相當於 -XX:MaxHeapSize(JVM最大堆大小)
-Xss 就相當於 -XX:ThreadStackSize(JVM線程)
舉個例子:
jps查看到某個pid(jps命令是查看Java進程用的),然後ps -ef查看這個pid的相關信息,可以看到很多相應的參數設置,如下:(jinfo -flags 直接跟pid可以列出所有的)
比如:如何查看某個進程使用的什麼GC ?
可以這樣看,先查到這個進程的進程號,然後可以這樣:
jinfo -flag 進程號 UseG1GC
jinfo -flag 進程號 UseParallelGC
jinfo -flag 進程號 UseConcMarkSweepGC
等
可以看一下這個進程使用了那種GC。
以上講的是JVM的參數類型。
JVM內存模型
參考官網:https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
內存模型如下圖:
.class字節文件通過CLASS LOADER加載進來之後,進入運行時數據區。運行時數據區並不是真正的內存結構,它只是定義了一個規範。
運行時數據區必看文檔:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5
內存結構
JDK1.8的的JVM內存結構圖如下:
垃圾回收的算法
垃圾回收的算法有哪些?
標記清除
複製
標記整理
分代垃圾回收
不同的區採用不同的垃圾回收機制。
JVM內存泄漏
舉例:在java裏面new了一個對象,你的指針一直都持有這個對象,不再使用且不再回收,這個指針一直被其它對象所持有,自動的垃圾回收機制無法把這個對象給釋放掉。慢慢的越積越多,到最後佔到JVM很多空間,其它代碼就無法運行了。想辦法找到這個對象並修改代碼。這個案例在hive裏面經常見到。