1. 程式人生 > >淺談JVM & GC

淺談JVM & GC

JVM & GC

1. 記憶體模型:

關於java的記憶體模型,我只想說一圖解千愁。話不多說,直接放圖. 在這裡插入圖片描述

2.GC

  1. 解釋: GC也就是java的垃圾回收機制

  2. 回收物件:既然是回收垃圾,那麼我們先要搞清回收的是哪部分內容。其實GC回收回收的物件是堆(包括java堆和方法區),主要回收的是java堆。

  3. 定義垃圾:既然是回收垃圾,那麼我們就需要先定義下什麼是垃圾。 方法一:引用計數器(已廢棄) 思想:為每個物件設定一個計數器,當其它地方引用該物件時,計數器+1;相應的,當引用失效時,計數器-1;當計數器等於0時,該物件即被定義為垃圾。 缺陷:不能解決迴圈引用 方法二:根搜尋演算法

    思想: 以GCRoot作為根結點,從這些根節點往下搜尋,當某物件不可達時,即被定義為垃圾。話不多說,直接上圖。 在這裡插入圖片描述

    如上圖ObjectA和ObjectB是可達的,ObjectC和ObjectD是不可達的。那麼C和D就會被回收。有效解決迴圈物件的回收問題。

  4. 回收垃圾 既然找到了垃圾,那麼怎麼清除呢。 方法一:標記-清除演算法 法如其名,分兩階段,第一階段標記垃圾物件,第二階段清除標記的垃圾物件。 缺陷:如下圖,假設灰色的方格為清除後的可用區域,很明顯,這麼區域是不連續的。 在這裡插入圖片描述 方法二:標記-整理演算法 不多說,大家已經猜的差不多了吧,沒錯,標記-整理演算法就是在標記-清除後將可用的空間往記憶體一端移動。這樣就有效的提高了記憶體的利用率。 方法三:複製演算法

    思想:把記憶體分為大小相等的兩塊,每次使用其中的一塊,當垃圾回收時,把存活的物件複製到另一塊上,然後將整塊記憶體清掉。 缺陷:記憶體利用率極低(畢竟一次只用一半) 這種演算法也很好理解,就不展示拙劣的畫技了。

  5. 既然有GC,為什麼還會記憶體溢位呢? 理論上講,java有垃圾回收機制,不會存在記憶體洩漏。但理想總是豐滿的,而現實總是骨感的。在實際開發中,記憶體中總會存在一些無用但可達的物件,那麼這些物件就不會被回收。如果一個物件引用被使用者無意識的儲存了,那麼該物件就永遠無法被回收,該物件引用的其它物件也無法被回收,比如Hibernate的一級快取。

  6. 記憶體溢位的主要原因及解決辦法 原因:

    1) 記憶體中載入的資料量過大,如一次從資料庫取出過多資料 2) 程式碼中存在死迴圈 3)使用的第三方軟體中的 BUG 解決方案: 1)修改 JVM 啟動引數,直接增加記憶體 2)檢查錯誤日誌 3)使用記憶體檢視工具