面試【JAVA基礎】JVM


一、內存模型

1.一、堆
  1. 堆是全部線程共享的,主要存放對象實例和數組。
  2. 新生代和老年代的比例是1:2。
  3. 新生代中三個區域的比例是 8 : 1 : 1。
1.1.一、新生代

對象分配在eden區中,當eden區滿時會觸發minor gc,將eden區中存活的對象,複製到survivor0區中,清空eden區,當survivor0中滿了時,會將存活的對象複製到survivor1區中,而後將survivor0和survivor1交換,保持survivor1是空的。每通過一次yong gc 年齡就+1。java

  • Eden

對象建立,對象分配在eden區,當eden區滿了,再建立對象的時候,會觸發minor gc,進行Eden和from surivior區域的垃圾回收。算法

  • FromServivor
  • ToSurvivor

minor gc後還存活的對象會被放入此區域,當對象年齡到達閾值後會進入老年代。或者to surivior區域滿了,會將對象放入老年代。數組

1.1.二、老年代
  1. 大對象,須要大量連續內存空間的對象
  2. 長期存活的對象,對象年齡超過15(默認值)
  3. yong gc後survivor區容不下的對象。
1.二、JVM棧

線程私有的,每一個線程都有一個棧,主要存放當前線程的局部變量,程序運行狀態,方法返回值,方法出口等。緩存

1.三、本地方法棧

爲虛擬機使用到的native方法服務。併發

1.四、方法區

用於存放已經被夾在的類信息,常量,靜態變量,1.8後取消了永久代,增長了元空間,元空間並不在虛擬機中,而是用的是本地內存。元空間中存放類的元信息,靜態變量和常量池移入堆中。app

1.五、程序計數器
  1. 程序私有,生命週期與程序相同
  2. 當前線程所執行的字節碼的行號指示器。
  3. 用來實現分支,循環,跳轉,異常等功能。

二、常量池中包括什麼

常量池在編譯時期肯定,存放在編譯生成的class文件中,包含了基本數據類型和對象類型(String和數組)jvm

三、如何判斷對象是否存活

使用什麼方法標記一個對象可回收?xss

  1. 引用計數法,每一個對象都有一個引用計數器,被引用+1 當引用數爲0即爲可被GC的對象
  2. 可達性分析:從根節點出發,向下搜索,未訪問到的對象標記爲不可達,可被回收

四、哪些對象能夠用爲GC ROOT對象

  1. 虛擬機棧中引用的對象。
  2. 方法區中靜態對象引用的對象。
  3. 方法區中常量引用的對象。
  4. 本地方法棧中引用的對象。

五、GC策略

  1. 標記清除法,從根節點進行掃描,對存活的對象進行標記,標記完成後,再掃描整個空間中未被標記的對象,進行清理。容易形成內存碎片
  2. 複製,將內存劃分爲兩份,當其中一分內存滿了時,從根節點掃描,將存活的對象複製到另外一分內存中。不會出現內存碎片問題,但須要兩倍的空間。
  3. 標記整理,如標記清除法同樣,標記對象,清除後將全部存活對象向左移。避免了內存碎片和兩倍空間的問題,但增長了移動對象的成本。

六、具體GC收集器

  1. 串行垃圾收集器,serial
  2. 並行垃圾收集器 parNew,parallel 注重吞吐量
  3. cms 注重最短回收停頓時間
  4. G1

cms和G1的區別 :工具

  • cms是新生代的垃圾收集器,採用標記清除。
  • G1是新生代和老年代的垃圾收集器,採用標記整理。
  • cms會產生內存碎片,G1並不會。
  • Cms追求最小停頓時間,G1是達到可控的停頓時間,儘量提升吞吐量。

七、什麼樣的對象進入老年代

  1. 大對象,須要大量連續內存空間的對象。
  2. 長期存活的對象,對象年齡超過15(默認值)。
  3. yong Gc後survivor區容不下的對象。

八、爲何要區分新生代和老年代

  1. 對象的生存狀況不一樣使用不一樣的GC算法。
  2. 新生代對象可能被頻繁的建立和回收,老年代回收較少。

九、survivor區存在的意義

  1. 爲了提升對象進入老年代的門檻,減小fullGC的次數,由於fullGC很耗時。
  2. 兩個survivor的做用是爲了減小survivor區的內存碎片。

十、什麼是yangGC

對年輕代進行gc。觸發條件:性能

  1. eden區不足

    • 清空eden from to中沒被引用的對象。
    • 將eden from中存活的對象 複製到 to中。
    • 將to中的對象晉升到old中,包括兩類對象,一個是年齡到達閾值,一個是to中放不下。
  2. full gc也會出發yong gc

十一、何時觸發fullGC

  1. 手動觸發的GC。
  2. 老年代的空間不足。
  3. 永久代的空間滿了(方法區)。
  4. 統計到yong gc晉升到老年代的平均大小大於老年代剩餘的大小(老年代的空間不足)。
  5. jvm自身固定頻率的fullGC(默認一小時執行一次)。

十二、內存的配置參數

  1. xms xmx 配置堆內存的最小和最大值
  2. xmn 年輕代內存的初始大小
  3. xss jvm棧大小

1三、對象分配內存的兩種方式

  1. 指針碰撞,若是內存對象是規整的,採用指針碰撞來爲對象分配內存,全部使用過的內存在指針的一側,未使用過的內存在指針的另外一側,分配內存只須要移動指針便可。
  2. 空閒列表,內存不規整,使用過的內存和未使用過的內存交織在一塊兒,維護一個內存使用列表,記錄那些內存是可用的,在分配的時候找到一塊足夠大的空間劃分給對象,並更新列表上的內容。

1四、如何減小GC的開銷

  1. 避免顯示的調用System.gc。
  2. 儘可能減小臨時對象的使用。
  3. 對象不使用時,最好顯式的置爲null。
  4. 儘可能使用StringBuffer而不用String累加字符串。
  5. 能用基本類型就是用基本類型。
  6. 儘可能少用靜態對象變量。

1五、什麼是JAVA內存模型(JMM)

用於屏蔽掉各類硬件和操做系統的內存訪問差別,以實現讓java程序在各個平臺下都能達到一致的併發效果。

1六、什麼時happens-before

  1. 保證了內存的可見性
  2. 制定了四個規則:

    • 程序順序規則:一個線程中的每一個操做 happens-before 與後續的全部操做。
    • 監視器鎖規則:一個監視器解鎖 happens-before 於 加鎖。
    • volatile變量規則: 寫操做 happens-before 讀操做。
    • 傳遞性 A happens-before B ,B happens-before C ,那麼Ahappens-before C。

1七、性能調優工具

17.一、jps

jps主要用來輸出jvm中運行的進程狀態信息。
-l 輸出main類或者jar的權限名。

17.二、jstack

jstack pid > log
能夠將線程堆棧轉存到文件中。
日誌分析可使用fastthread.io。

17.三、jstat

能夠顯示出虛擬機進程中的classloader、內存、gc等運行數據。
參數
-class pid 類加載統計。
-gc 垃圾回收統計 ,後面跟兩個參數一個是間隔輸出時間,一個是總共輸出次數。
gc日誌可使用 gceasy.io

17.四、jmap

jmap查看堆內存的使用狀況:
jmap pid

17.五、jinfo

查看java程序的運行環境參數:
jinfo pid

1八、內存柵欄

經過確保從另外一個CPU來看,屏障的兩邊的全部指令都是正確的程序順序,而保持程序順序的外部可見性;其次能夠實現內存數據可見性,確保內存數據會同步到CPU緩存子系統。

1九、JVM產生的內存溢出及解決辦法

  1. java heap space

代碼中存在大對象的分配,屢次GC後仍找不到分配空間。
解決辦法:查看是否有大對象分配尤爲是大數組。經過jmap把堆內存的日誌dump下來,分析日誌,若是解決不了增長堆內存的空間。

  1. permspace metaspace

永久代或元空間溢出。生成大量的代理類或者使用自定義的類加載器。
解決辦法:查看有沒有配置永久代或者元空間的大小。是否長時間沒有重啓jvm,是否有大量的反射操做。

tencent.jpg

相關文章
相關標籤/搜索