java學習筆記之: JVM一:內存

寫在前頭:看書入門, java玩了這麼久了,也沒仔細研究下這種重要的基礎部分,最近抽空在看”深入理解java虛擬機 JVM高級特性與最佳實踐“,寫點學習總結;

一.內存結構
a.我們常說java內存結構=堆+棧,實際上這只是我們最常出問題的地方,我們最終要重點研究的也是這一部分
b. 虛擬機的規定呢?–>堆+棧+程序計數器,直接上圖
這裏寫圖片描述
棧還存放着動態鏈接: 運行時實時編譯成實際的實現類,實現動態編譯
當然 這裏的方法區是存在爭議的,因爲不同虛擬機廠商/版本會有差異,棧也分虛擬機棧和本地方法棧,合在一塊理解更容易
其中 通過存儲內容可以明顯看出,棧和程序計數器是線程獨享的,堆是線程共享的

二.StackOverFlowError & OutOfMemoryError

三.創建對象
這裏寫圖片描述
當然還有疑問啦 後續再補充
怎麼去定位對象呢? –>句柄池和直接指針訪問兩中方法,差異就在於是否把堆中的對象的地址單獨存放在句柄池(堆)中,這樣垃圾回收時造成對象移動時是否去改變棧中的引用地址的值,改句柄池的值就行

四.回收對象

首先需要明確一下我們的目標   

a、java在線程中,運行了一段代碼,有這麼個局部變量myclass A,A的引用地址存在棧,程序走到哪存在計數器,對象A的具體內容存在堆中,線程結束了,局部變量就失效了,計數器走到最後一步了,這兩部分裏存到數據就直接刪掉得了嘛,隨線程而生隨線程而滅,
並且棧幀之類的在編譯期間就已經確定了,內存回收和分配都有確定型,沒什麼好研究的
b、但是堆裏面的內容就不一定了 搞不好其他地方還在引用 –>線程共享的數據 沒法簡單的回收,所以我們所研究的垃圾收集器相關的東西 都是針對堆的

  1. 誰是垃圾?

    沒人要了就是垃圾
    a.引用計數算法(淘汰了):引用一次就計數+1,爲0就是垃圾,but無法解決循環引用的問題 如下
    Object A = B
    Object B = A

    b.可達性分析算法(GC roots算法/根節點搜索算法):
    從根節點出發找不到的就是垃圾 如上的從A找能找到B對象 B就是活的 能解決循環引用的問題,關鍵點在於哪些是GC roots
    這裏寫圖片描述

  2. 什麼時候回收

    cpu空閒的時候/堆滿了 或者達到設定比例值了就GC/FULL GC
    
  3. 怎麼回收

    先介紹垃圾回收算法:標記清除,複製算法,標記整理,分代(並不是單獨的算法)
    算法的具體實現:
    以sun的Hotspot的實現爲例

    1.Serial/SerialOld 串行收集器
    2.ParNew 並行收集器
    3.Pareller Scavenge/Pareller Old 吞吐量優先收集器
    4.CMS Concurrent Mark Sweep併發收集器(老年代)
    5.G1 垃圾優先收集器
    每種收集器年輕代/老年代組合可以得到不同效果,同時也可以設定備用收集器
    
    串行:暫停工作線程,運行一個GC線程
    並行:暫停工作線程 , 併發運行多個GC線程 只是GC線程併發而已
    併發:併發運行工作線程和GC線程  這纔是我們常說的併發
    

    從線程的哪個步驟開始回收呢?

    安全點/安全區域
    

    回收的步驟呢?

    每個收集器的步驟不一樣,但無外乎標記和清除
    

    這裏寫圖片描述

五.內存的分配和回收策略
內存分配和回收策略
其基本策略稱之爲擔保策略,因爲GC前不確定能存活多少對象,所以Minor GC是有風險的,有可能survivor to裝不下,就需要老年代做擔保,但即便擔保 也有可能失敗,失敗了就要FULL GC,如果設置HandlePromotionFailure爲不允許擔保失敗,則直接FULL GC以防止擔保失敗

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章