Java面試知識點(五十二)虛擬機 分配內存

在類加載檢查通過後,接下來虛擬機將爲新生對象分配內存。對象所需的內存大小在類加載完成後便可確定,爲對象分配空間的任務等同於把一塊確定大小的內存從 Java 堆中劃分出來。分配方式有 “指針碰撞”“空閒列表” 兩種,選擇那種分配方式由 Java 堆是否規整決定,而 Java 堆是否規整又由所採用的垃圾收集器是否帶有壓縮整理功能決定。

內存分配的兩種方式:

  • 指針碰撞
  • 空閒列表

選擇以上兩種方式中的哪一種,取決於 Java 堆內存是否規整。而 Java 堆內存是否規整,取決於 GC 收集器的算法是 “標記 - 清除”,還是 “標記 - 整理”(也稱作 “標記 - 壓縮”),值得注意的是,複製算法內存也是規整的

指針碰撞

  1. 適用場合
    堆內存規整,沒有內存碎片
  2. 原理
    用過的內存全部整合到一邊,沒有用過的內存放在另一邊,中間有一個分界指針,只需要向着沒有用過的內存區域移動對象內存大小位置即可
  3. GC收集器
    Serial、parNew

空閒列表

  1. 適用場合
    堆內存不規整,有內存碎片
  2. 原理
    虛擬機會維護一個列表,該列表會記錄那些內存是可用的,在分配的時候找一個足夠大的內存區域劃分給對象實例,並更新列表
  3. GC收集器
    CMS

內存分配併發問題

在創建對象的時候有一個很重要的問題,就是線程安全,因爲在實際開發過程中,創建對象是很頻繁的事情,作爲虛擬機來說,必須要保證線程是安全的,通常來講,虛擬機採用兩種方式來保證線程安全:

  • CAS + 失敗重試: CAS 是樂觀鎖的一種實現方式。所謂樂觀鎖就是,每次不加鎖而是假設沒有衝突而去完成某項操作,如果因爲衝突失敗就重試,直到成功爲止。虛擬機採用 CAS 配上失敗重試的方式保證更新操作的原子性。
  • TLAB: 爲每一個線程預先在 Eden 區分配一塊兒內存,JVM 在給線程中的對象分配內存時,首先在 TLAB 分配,當對象大於 TLAB 中的剩餘內存或 TLAB 的內存已用盡時,再採用上述的 CAS 進行內存分配
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章