JVM面试专题
目錄
1.內存模型以及分區,需要詳細到每個區放什么??
2.堆里面的分區:Eden,survival (from+ to),老年代,各自的特點。
3.GC 的兩種判定方法:
4.GC 的三種收集方法:標記清除、標記整理、復制算法的原理與特點,分別用在什么地方,如果讓你優化收集方法,有什么思路?
5.GC 收集器有哪些?CMS 收集器與 G1 收集器的特點。
6.Minor GC 與 Full GC 分別在什么時候發生?
7.簡述 java 垃圾回收機制??
8.java 中垃圾收集的方法有哪些?
9.簡述 java 類加載機制??
10.什么是類加載器,類加載器有哪些??
11.說一下 JVM 調優的工具?
12.常用的 JVM 調優的參數都有哪些?
1.內存模型以及分區,需要詳細到每個區放什么?
JVM 分為堆區和棧區,還有方法區,初始化的對象放在堆里面,引用放在棧里面,class 類信息常量池(static 常量和 static 變量)等放在方法區 a、方法區:主要是存儲類信息,常量池(static 常量和 static 變量),編譯后的代碼(字節碼)等數 b、堆:初始化的對象,成員變量 (那種非 static 的變量),所有的對象實例和數組都要在堆上分配 c、棧:棧的結構是棧幀組成的,調用一個方法就壓入一幀,幀上面存儲局部變量表,操作數棧,方法出口等信息,局部變量表存放的是 8 大基礎類型加上一個應用類 型,所以還是一個指向地址的指針 d、本地方法棧:主要為 Native 方服務 e、程序計數器:記錄當前線程執行的行號2.堆里面的分區:Eden,survival (from+ to),老年代,各自的特點。
a、堆里面分為新生代和老生代(java8 取消了永久代,采用了 Metaspace),新生代包含 Eden+Survivor 區,survivor 區里面分為from 和 to 區, 內存回收時,如果用的是復制算法,從 from 復制到 to,當經過一次或者多次 GC 之后,存活下來的對象會被移動到老年區,當 JVM 內存不夠用的時候,會觸發 Full GC,清理 JVM 老年區當新生區滿了之后會觸發 YGC,先把存活的對象放到其中一個 Survice區,然后進行垃圾清理。 b、因為如果僅僅清理需要刪除的對象,這樣會導致內存碎片,因此一般會把 Eden 進行完全的清理,然后整理內存。那么下次 GC 的時候,就會使用下一個Survive,這樣循環使用。如果有特別大的對象,新生代放不下,就會使用老年代的擔保,直接放到老年代里面。因為 JVM 認為,一般大對象的存活時間一般比較久遠。3.GC 的兩種判定方法:
a、引用計數法:指的是如果某個地方引用了這個對象就+1,如果失效了就-1,當為 0 就會回收但是 JVM 沒有用這種方式,因為無法判定相互循環引用(A 引用 B,B 引用 A)的情況 b、引用鏈法: 通過一種 GC ROOT 的對象(方法區中靜態變量引用的對象等-static 變量)來判斷,如果有一條鏈能夠到達 GC ROOT 就說明,不能到達 GC ROOT 就說明可以回收4.GC 的三種收集方法:標記清除、標記整理、復制算法的原理與特點,分別用在什么地方,如果讓你優化收集方法,有什么思路?
先標記,標記完畢之后再清除,效率不高,會產生碎片復制算法:分為 8:1 的 Eden 區和survivor 區,就是上面談到的 YGC標記整理:標記完畢之后,讓所有存活的對象向一端移動。5.GC 收集器有哪些?CMS 收集器與 G1 收集器的特點。
a、并行收集器:串行收集器使用一個單獨的線程進行收集,GC 時服務有停頓時b、間串行收集器:次要回收中使用多線程來執行 c、CMS 收集器是基于“標記—清除”算法實現的,經過多次標記才會被清除 d、G1 從整體來看是基于“標記—整理”算法實現的收集器,從局部(兩個 Region 之間)上來看是基于“復制”算法實現的6.Minor GC 與 Full GC 分別在什么時候發生?
新生代內存不夠用時候發生 MGC 也叫 YGC,JVM 內存不夠的時候發生 FGC7.簡述 java 垃圾回收機制?
在 java 中,程序員是不需要顯示的去釋放一個對象的內存的,而是由虛擬機自行執行。在JVM 中,有一個垃圾回收線程,它是低優先級的,在正常情況下是不會執行的,只有在虛擬機空閑或者當前堆內存不足時,才會觸發執行,掃面那些沒有被任何引用的對象,并將它們添加到要回收的集合 中,進行回收。8.java 中垃圾收集的方法有哪些?
a、標記-清除:這是垃圾收集算法中最基礎的,根據名字就可以知道,它的思想就是標記哪些要被回收的對象,然后統一回收。這種方法很簡單,但是會有兩個主要問題:1.效率不高,標記和清除的效率都很低;2.會產生大量不連續的內存碎片,導致以后程序在分配較大的對象時,由于沒有充足的連續內存而提前觸發一次 GC 動作。 b、復制算法:為了解決效率問題,復制算法將可用內存按容量劃分為相等的兩部分,然后每次只使用其中的一塊,當一塊內存用完時,就將還存活的對象復制到第二塊內存上,然后一次性清楚完第一塊內存,再將第二塊上的對象復制到第一塊。但是這種方式,內存的代價太高,每次基本上都要浪費一般的內存。于是將該算法進行了改進,內存區域不再是按照 1:1 去劃分,而是將內存劃分為8:1:1 三部分,較大那份內存交 Eden 區,其余是兩塊較小的內存區叫 Survior 區。每次都會優先使用 Eden 區,若 Eden 區滿,就將對象復制到第二塊內存區上,然后清除 Eden 區,如果此時存活的對象太多,以至于 Survivor 不夠時,會將這些對象通過分配擔保機制復制到老年代中。(java 堆又分為新生代和老年代) c、標記-整理:該算法主要是為了解決標記-清除,產生大量內存碎片的問題;當對象存活率較高時,也解決了復制算法的效率問題。它的不同之處就是在清除對象的時候現將可回收對象移動到一端,然后清除掉端邊界以外的對象,這樣就不會產生內存碎片了。 d、分代收集:現在的虛擬機垃圾收集大多采用這種方式,它根據對象的生存周期,將堆分為新生代和老年代。在新生代中,由于對象生存期短,每次回收都會有大量對象死去,那么這時就采用復制算法。老年代里的對象存活率較高,沒有額外的空間進行分配擔保,所以可以使用標記-整理 或者 標記-清除。9.簡述 java 類加載機制?
虛擬機把描述類的數據從 Class 文件加載到內存,并對數據進行校驗,解析和初始化,最終形成可以被虛擬機直接使用的 java 類型。10.什么是類加載器,類加載器有哪些?
實現通過類的權限定名獲取該類的二進制字節流的代碼塊叫做類加載器。主要有一下四種類加載器: a、啟動類加載器(Bootstrap ClassLoader)用來加載 java 核心類庫,無法被 java 程序直接引用。 b、擴展類加載器(extensions class loader):它用來加載 Java 的擴展庫。Java 虛擬機的實現會提供一個擴展庫目錄。該類加載器在此目錄里面查找并加載 Java 類。 c、 系統類加載器(system class loader):它根據 Java 應用的類路徑(CLASSPATH)來加載 Java 類。一般來說,Java 應用的類都是由它來完成加載的。可以通過ClassLoader. getSystemClassLoader()來獲取它。 d、用戶自定義類加載器,通過繼承 java.lang.ClassLoader 類的方式實現。11.說一下 JVM 調優的工具?
JDK 自帶了很多監控工具,都位于 JDK 的 bin 目錄下,其中最常用的是 jconsole 和 jvisualvm 這兩款視圖監控工具。 jconsole:用于對 JVM 中的內存、線程和類等進行監控; jvisualvm:JDK 自帶的全能分析工具,可以分析:內存快照、線程快照、程序死鎖、監控內存的變化、gc 變化等。12.常用的 JVM 調優的參數都有哪些?
a、-Xms2g:初始化推大小為 2g; b、-Xmx2g:堆最大內存為 2g; c、-XX:NewRatio=4:設置年輕的和老年代的內存比例為 1:4; d、-XX:SurvivorRatio=8:設置新生代 Eden 和 Survivor 比例為 8:2; e、–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器組合; f、-XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器組合; g、-XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器組合; h、-XX:+PrintGC:開啟打印 gc 信息; i、-XX:+PrintGCDetails:打印 gc 詳細總結
- 上一篇: setp函数--Matplotlib
- 下一篇: java/php/net/python作