今天在技術羣裏被大佬問了一堆jvm的問題。。收集記錄下來。。並且附上我的答案(沒有百度的,不可盡信,僅僅是我看《深入理解java虛擬機》的粗淺回答)
1、堆被分成了新生代和老年代,什麼對象會進入老年代。
答:
(1)大對象(對象大小超過設定的閾值),直接到老年代。
(2)在年輕代survivor區域存活minor gc次數超過指定次數的對象。默認是15次。可通過參數設置。
(3)survivor中存活的對象,存活次數相同的對象內存總和大小超過survivor的一半,那麼大於等於這個存活次數的對象都會進入到老年代。
2、如何判斷對象是否可回收?
(1)根據GC roots 進行可達性分析。
3、哪些對象可以做GC roots?
(1)、虛擬機棧中的每個棧幀中的局部變量表中的對象(即正在被調用的方法中的局部變量)
(2)、方法區中靜態變量
(3)、方法區運行時常量池裏的引用類型常量。(運行時常量池除了String和其他基本類型的包裝類,還有啥引用類型?而String和包裝類是不可變的啊)
(4)、本地方法棧中使用的對象。(這個不懂)
4、如何解決內存泄漏?
這個就要好好利用jdk本身提供的jmap工具了。
(1)用jmap把堆的當前快照文件拿到。
(2)使用專門的工具解析這個快照文件,貌似jdk裏也有一個工具可以簡單解析,轉爲圖形界面。
(3)使用jmap本身參數可以查看佔用內存對象。
(4)定位到具體代碼,然後修改代碼。
5、死鎖如何解決?
使用jstack工具可以查詢當前堆棧信息,並且會判斷死鎖標識。。
阿里開源的arthas也可以查看。。
6、觸發gc的條件有哪些?
(1)年輕代內存不夠了,觸發minor GC
(2)老年代內存不夠了,觸發full GC/major GC
(3)方法區(永久代)內存不夠了,觸發Full GC
(4)minor GC時,如果有存活對象要晉升到老年代,如果老年代剩餘空間大小小於歷次平均晉升的對象大小,那麼老年代會進行GC,此時是Full GC。
(5)代碼中使用System.gc,會建議垃圾收集進行GC,但GC不一定聽取建議。。不過在滿足某些條件時還是會聽取建議的(項目中一般不顯示這麼調用,本來就不一定立即生效)
(6)所謂大對象,是指需要大量連續內存空間的java對象,例如很長的數組,此種對象會直接進入老年代,而老年代雖然有很大的剩餘空間,但是無法找到足夠大的連續空間來分配給當前對象,此種情況就會觸發JVM進行Full GC。