六部分內容:
一。內存模型
1.程序計數器,方法區,堆,棧,本地方法棧的作用,保存那些數據
可以畫個大圖出來,很清晰
jvm內存模型主要指運行時的數據區,包括5個部分。
棧也叫方法棧,是線程私有的,線程在執行每個方法時都會同時創建一個棧幀,用來存儲局部變量表、操作棧、動態鏈接、方法出口等信息。調用方法時執行入棧,方法返回時執行出棧。
本地方法棧與棧類似,也是用來保存線程執行方法時的信息,不同的是,執行java方法使用棧,而執行native方法使用本地方法棧。
程序計數器保存着當前線程所執行的字節碼位置,每個線程工作時都有一個獨立的計數器。程序計數器為執行java方法服務,執行native方法時,程序計數器為空。
棧、本地方法棧、程序計數器這三個部分都是線程獨占的。
堆是jvm管理的內存中最大的一塊,堆被所有線程共享,目的是為了存放對象實例,幾乎所有的對象實例都在這里分配。當堆內存沒有可用的空間時,會拋出OOM異常。根據對象存活的周期不同,jvm把堆內存進行分代管理,由垃圾回收器來進行對象的回收管理。
方法區也是各個線程共享的內存區域,又叫非堆區。用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據,
jdk1.7中的永久代和1.8中的metaspace都是方法區的一種實現。
面試回答此知識點相關問題時,要答出兩個要點:一個是各部分的功能,另一個是哪些線程共享,哪些獨占。
二。類加載機制
1.雙親委派的加載機制
2.常用類加載器以及作用
3.雙親委派加載機制好處
4.如何判斷是同一個class
三。GC垃圾回收
1.分代回收的思想和依據
java堆內存被分代管理,主要是為了方便垃圾回收。
因為,第一,大部分對象很快就不使用了
第二,有一部分不會立即無用,但也不會持續很長的時間!
所以堆內存進行分代管理的划分!
2.不同垃圾回收算法實現的思路以及適用的場景
按類型分為3種:
引用計數法:通過對象被引用的次數來確定對象是否被使用,缺點無法解決循環引用的問題!
復制算法:需要from和to兩塊大小相同的內存空間。對象分配只在from塊,回收時把存活對象復制到to塊,清空from,然后調換職權!from變成to,to變成from!缺點,內存使用率低!
標記清除算法:分為標記對象和清除不再使用的對象 兩個階段! 缺點,會產生內存碎片!
jvm中,年輕代回收算法serial、parNew、parallel scavenge都是復制算法!
CMS、G1、zgc都屬於標記清除算法!
四。性能調優
1.常用jvm優化參數的作用
2.參數調優的依據
3.了解常用的jvm分析工具能分析哪類問題,以及使用方法
五。執行模式
1.解釋,編譯,混合模式的優缺點
2.了解java7提供的分層編譯技術
3.知道JIT即時編譯技術和OSR棧上替換
4.知道C1,C2編譯器針對的場景,其中C2針對server模式,優化更激進
5.java10提供的由java實現的graal編譯器
六。編譯優化
1.前端編譯器javac的編譯過程
2.AST抽象語法書
3.編譯期優化
4.運行期優化
5.編譯優化的常用技術
包括公共子表達式的消除,方法內聯,逃逸分析,棧上分配,同步消除等!明白了這些,才能寫出對編譯器友好的代碼!
1.JVM內存模型
- Java堆:線程共享的,唯一目的就是用於存放對象實例,是垃圾收集器管理的主要區域;
- Java虛擬機棧:線程私有的,每個方法在執行的同時都會創建一個棧幀用於存儲局部變量等,局部變量表存放了編譯器可知的各種基本數據類型和對象引用;
- 本地方法棧:和虛擬機棧類似,不過它是為Native方法服務;
- 程序計數器:線程私有的,可以看作是當前線程所執行的字節碼的行號指示器,以便線程切換后恢復執行使用;
- 方法區:線程共享的,用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據;該區域的內存回收主要是針對常量池的回收和類型的卸載(特別是要注意一些動態字節碼框架和自定義ClassLoader的場景下);在HotSpot里經常被稱為永久代,在Java 8里已被廢除了,被元空間取代;
===============================================================
2.JVM內存回收機制
1》堆內存
堆內存是所有線程共有的,可以分為兩個部分:年輕代和老年代。下圖中的Perm代表的是永久代,但是注意永久代並不屬於堆內存中的一部分,同時jdk1.8之后永久代也將被移除。
2》垃圾回收主要作用在堆內存
3》新生代(Young Generation):用於存放新創建的對象,采用復制回收方法,如果在s0和s1之間復制一定次數后,轉移到年老代中。這里的垃圾回收叫做minor GC;
4》老年代(Old Generation):這些對象垃圾回收的頻率較低,采用的標記整理方法,這里的垃圾回收叫做 major GC。
拓展:1.在進行垃圾回收的時候,怎么判斷哪些對象是垃圾,要被回收
通過兩種方式
1》引用計數【但是引用計數的方式無法解決循環引用的問題】
2》可達性分析
拓展:2.什么叫對象可達,什么叫對象不可達,什么是可達性分析
通過一系列稱為“GC Roots”的對象(比如虛擬機棧引用的對象、方法區中的類靜態屬性和常量引用對象)作為起點,從這些節點一直往下搜索,走過的路徑稱為引用鏈;而那些沒有與引用鏈相連的對象即為不可達,會被回收。
拓展:3.判斷對象可以回收的情況
1》對象顯式的置空null
2》局部引用指向的對象
3》弱引用關聯的對象
===============================================================
3.什么是GC,常用的GC算法有哪些?
1》GC就是垃圾回收機制,就是JVM對內存中的對象進行管理的一個過程
2》GC的過程如下:
1. Eden區最大,對外提供堆內存。當Eden區快要滿了,則進行Minor GC,把存活對象放入Survivor A區,清空Eden區;
2. Eden區被清空后,繼續對外提供堆內存;
3. 當Eden區再次被填滿,此時對Eden區和Survivor A區同時進行Minor GC,把存活對象放入Survivor B區,同時清空Eden 區和Survivor A區;
4. Eden區繼續對外提供堆內存,並重復上述過程,即在Eden區填滿后,把Eden區和某個Survivor區的存活對象放到另一個Survivor區;
5. 當某個Survivor區被填滿,且仍有對象未被復制完畢時或者某些對象在反復Survive 15次左右時,則把這部分剩余對象放到Old區;
6. 當Old區也被填滿時,進行Major GC,對Old區進行垃圾回收。
3》新生代采用的GC算法是 復制算法,而老年代采用的是標記-清除算法
4》復制算法就是 eden區往s0復制,或者往s1復制的過程,默認次數15次
5》標記-清除算法 是老年區依舊在用的對象標記可可達對象 清除就是清除不可達的對象。
拓展:GC觸發條件
GC類型 | 觸發條件 | 觸發時發生了什么 | 注意 | 查看方式 |
YGC | eden空間不足 | 清空Eden+from survivor中所有no ref的對象占用的內存 重新調整Eden 和from的大小(parallel GC會觸發此項) |
全過程暫停應用 是否為多線程處理由具體的GC決定 |
jstat –gcutil gc log |
FGC | old空間不足 |
清空heap中no ref的對象 permgen中已經被卸載的classloader中加載的class信息 如配置了CollectGenOFirst,則先觸發YGC(針對serial GC) 如配置了ScavengeBeforeFullGC,則先觸發YGC(針對serial GC) |
全過程暫停應用 是否為多線程處理由具體的GC決定 是否壓縮需要看配置的具體G |
===============================================================
4.你是通過什么方式實現JVM優化的?
1》調整新生代、s0、s1比例以及調整新生代 老年代的大小,目的是減少GC次數
2》不要顯示的調用system.GC()
3》對象不用的時候顯式的置為null
4》盡量減少局部變量的使用
5》盡量使用基本數據類型而不使用封裝類
6》盡量少使用靜態變量,因為靜態變量屬於類的變量,是全局變量,會一直占用資源
7》盡量分散的創建對象,不要一次性創建多個對象。
8》https://www.cnblogs.com/sxdcgaq8080/p/10649367.html
===============================================================
5.內存溢出和內存泄漏的區別
https://www.cnblogs.com/panxuejun/p/5883044.html
===============================================================