JVM內存回收區域+對象存活的判斷+引用類型+垃圾回收線程


此文已由做者趙計剛薪受權網易雲社區發佈。html

歡迎訪問網易雲社區,瞭解更多網易技術產品運營經驗。前端


注意:本文主要參考自《深刻理解Java虛擬機(第二版)》java

說明:查看本文以前,推薦先知道JVM內存結構,見《第一章 JVM內存結構安全

一、內存回收的區域服務器

  • 堆:這是GC的主要區域框架

  • 方法區:回收兩樣東西測試

    • 無用的類spa

    • 廢棄的常量.net

  • 棧和PC寄存器是線程私有區域,不發生GC線程

 

二、怎樣判斷對象是否存活

垃圾回收:回收掉死亡對象所佔的內存。判斷對象是否死亡,有兩種方式:

  • 引用計數法

    • 每次爲對象賦值時,都要進行計數器值的增減,消耗較大

    • 對於A、B相互引用這種狀況處理不了(這一點是不用的主要緣由)

    • 原理:給對象添加一個引用計數器,每當有一個地方引用它時,計數器值+1;引用失效時,計數器值-1

    • 實際中不用,不用的兩個緣由

  • 可達性分析(跟蹤收集)

    • 原理:從根集合(GC Roots)開始向下掃描,根集合中的節點能夠到達的節點就是存活節點,根集合中的節點到達不了的節點就是將要被回收的死亡節點,以下圖中的A/B/C是存活節點,D/E是死亡節點:



    • Java棧中的對象引用(存在於局部變量表中,注意:局部變量表中存放的是基本數據類型和對象引用)

    • 方法區中:常量+靜態(static)變量

    • 傳到本地方法中,尚未被本地方法釋放的對象引用

    • 這是垃圾回收最多考慮的地方,因此有時,咱們也會將死亡對象稱爲"沒有引用指向的對象"

    • 根集合中的節點包括:簡單來說,就是全局性的引用(常量和靜態屬性)和棧引用(下邊第1、三)

 

三、3種引用類型

  • 強引用(Strong Reference):A a = new A();//a是強引用

  • 軟引用(Soft Reference):當內存不足時,釋放軟引用所引用的對象;當內存足夠時,就是一個普通對象(強引用)

  • 弱引用(Weak Reference):弱引用對象只能存活到下一次垃圾回收以前,一旦發生垃圾回收,馬上被回收掉

 

四、方法區的回收

  • 廢棄常量:例如,沒有任何一個引用指向常量池中的"abc"字符串,則"abc"字符串被回收

  • 無用的類:知足如下三個條件

    • Java堆中不存在該類的任何實例

    • 加載該類的ClassLoader被回收

    • 該類的Class對象沒有在任何地方被引用

注意:

  • 在實際開發中,儘可能不用JSP去作前端,而是用velocity、freemarker這樣的模板引擎去作

  • 與類相關經常使用的三個參數:

    • -XX:+PrintClassHistogram:輸出類統計狀態

    • -XX:-TraceClassLoading:打印類加載信息

    • -XX:-TraceClassUnloading:打印類卸載信息

 

五、垃圾回收線程

系統的垃圾回收是由垃圾回收線程來檢測操做的,該線程是一個後臺線程(daemon thread)。

5.一、後臺線程與咱們使用的前臺線程而言,有一個特色:當JVM中的前臺線程數量爲0時,後臺線程自動消亡。能夠這樣講,後臺線程依託於前臺線程而存在。

5.二、垃圾回收線程爲何要設置成爲後臺線程呢?

咱們想一下,當前臺一個線程都沒有時,垃圾還會有嗎?或者說垃圾回收還有必要嗎?答案是沒有必要,因此此時垃圾回收線程也就失去了存活的意義。

因此能夠這樣講,將一個線程是否設置爲後臺線程,就看這條線程在沒有其餘線程存在的狀況下,是否還有存活的意義。

例如,在咱們使用Apache mina2作RPC時,咱們在消息的接收端直接開啓一個後臺線程啓動服務來接受消息發送端發來的消息事件請求就能夠。試着去想,若是在整個JVM中只有當前的這一個後臺線程了,那麼這個線程還有必要存活下來嗎?固然沒有必要,由於消息永遠都不會再發送了(前臺線程都沒了)

 

免費領取驗證碼、內容安全、短信發送、直播點播體驗包及雲服務器等套餐

更多網易技術、產品、運營經驗分享請點擊


相關文章:
【推薦】 [翻譯]pytest測試框架(一)
【推薦】 dubbo事件通知機制(1)
【推薦】 debian 7上源碼編譯MongoDB 3.4版本

相關文章
相關標籤/搜索