程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> JVM中的垃圾回收

JVM中的垃圾回收

編輯:C++入門知識

JVM中的垃圾回收


GC

垃圾回收回收什麼

Java的內存分配原理與C/C++不同,C/C++每次申請內存時都要malloc進行系統調用,而系統調用發生在內核空間,每次都要中斷進行切換,這需要一定的開銷.

而Java虛擬機是先一次性分配一塊較大的空間,然後每次new時都在該空間上進行分配和釋放,減少了系統調用的次數,節省了一定的開銷。節省開銷的同時,我們也必須對其進行垃圾的檢測和回收。

java一般內存申請有兩種:靜態內存和動態內存。很容易理解,編譯時就能夠確定的內存就是靜態內存,即內存是固定的,系統一次性分配,比如int類型變量;動態內存分配就是在程序執行時才知道要分配的存儲空間大小,比如java對象的內存空間。根據上面我們知道,java棧、程序計數器、本地方法棧都是線程私有的,線程生就生,線程滅就滅,棧中的棧幀隨著方法的結束也會撤銷,內存自然就跟著回收了。所以這幾個區域的內存分配與回收是確定的,我們不需要管的。但是java堆和方法區則不一樣,我們只有在程序運行期間才知道會創建哪些對象,所以這部分內存的分配和回收都是動態的。一般我們所說的垃圾回收也是針對的這一部分。

垃圾回收主要是針對堆空間和方法區的。

GC策略

垃圾檢測

垃圾檢測存在兩種策略,第一種是引用計數,第二種是可達性分析。

引用計數是給對象添加一個引用計數器,另外一個對象引用它,計數器自增,反之自減。但這樣的引用計數存在一定問題,若存在兩個對象A,B互相引用,而沒有外部對象引用它們。這時,這兩個垃圾對象不能被檢測出來。 可達性分析是以根集對象(棧中對象、方法區常量對象等)作為起點,向下搜索,如果不能搜索到的對象就是垃圾對象,可以進行回收。如果采用Dijkstra算法,其時間復雜對為O(m),m為對象個數。

垃圾回收

垃圾回收按照基本回收策略分有以下回收策略

按策略分類

引用計數:

對於引用計數來說,回收引用數為0的對象即可,但其存在致命缺陷即不能處理循環引用的問題

復制(copying):

此算法將內存分為兩個區域,內存的分配每次只使用其中一個區域(兩次gc之間)。回收時將標記為垃圾的對象清除,把標記為非垃圾的對象復制到另一個區域中。

\

此算法速度快,不會出現內存碎片,可並發實現。但是缺點也很明顯,即需要兩倍的內存空間。

標記-清除(Mark-Sweep):

對標記為垃圾的對象進行清除,不整理。

\vc8gPGNvZGU+seq8x9X7wO08L2NvZGU+ILe9t6i/7KOssrvAy7fRtu7N4rXExNq05r/VvOSjrL/J0tSyoreiyrXP1qGjtau74bL6yfrE2rTmy+nGrKOs0KfCyrK7uN+hozwvcD4NCjxoNSBpZD0="標記-整理mark-compact">標記-整理(Mark-Compact):

對標記為垃圾的對象進行清除,清除後進行整理,按順序存放。

\

此算法避免了復制標記清除的缺點,不浪費內存空間,同時不會產生內存碎片。但其速度是最慢的,且難以並發實現。

按系統線程分類

串行收集:

串行收集使用單線程處理所有垃圾回收工作,因為無需多線程交互,實現容易,而且效率比較高。但是,其局限性也比較明顯,即無法使用多處理器的優勢,所以此收集適合單處理器機器。當然,此收集器也可以用在小數據量(100M左右)情況下的多處理器機器上。

並行收集:

並行收集使用多線程處理垃圾回收工作,因而速度快,效率高。而且理論上CPU數目越多,越能體現出並行收集器的優勢。

並發收集:

相對於串行收集和並行收集而言,前面兩個在進行垃圾回收工作時,需要暫停整個運行環境,而只有垃圾回收程序在運行,因此,系統在垃圾回收時會有明顯的暫停,而且暫停時間會因為堆越大而越長。

JVM中的實際GC

JVM使用分代收集算法。分代的垃圾回收策略,是基於這樣一個事實:不同的對象的生命周期是不一樣的。因此,不同生命周期的對象可以采取不同的收集方式,以便提高回收效率。

為什麼要運用分代垃圾回收策略?在java程序運行的過程中,會產生大量的對象,因每個對象所能承擔的職責不同所具有的功能不同所以也有著不一樣的生命周期,有的對象生命周期較長,比如Http請求中的Session對象,線程,Socket連接等;有的對象生命周期較短,比如String對象,由於其不變類的特性,有的在使用一次後即可回收。

試想,在不進行對象存活時間區分的情況下,每次垃圾回收都是對整個堆空間進行回收,那麼消耗的時間相對會很長,而且對於存活時間較長的對象進行的掃描工作等都是徒勞。因此需要進行分層,不同生命存活時間的對象使用不同回收方法。

如何劃分?將對象按其生命周期的不同劃分成:年輕代(Young Generation)、年老代(Old Generation)、持久代(Permanent Generation)。其中持久代主要存放的是類信息,所以與java對象的回收關系不大,與回收息息相關的是年輕代和年老代。

\Java堆(包括新生代,老年代)。

基於標記-整理算法,不產生內存碎片。

可以非常精確控制停頓時間,在不犧牲吞吐量前提下,實現低停頓垃圾回收。

G1收集器避免全區域垃圾收集,它把堆內存劃分為大小固定的幾個獨立區域,並且跟蹤這些區域的垃圾收集進度,同時在後台維護一個優先級列表,每次根據所允許的收集時間,優先回收垃圾最多的區域。
區域劃分和優先級區域回收機制,確保G1收集器可以在有限時間獲得最高的垃圾收集效率。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved