當前位置:首頁 » 操作系統 » jvm回收演算法

jvm回收演算法

發布時間: 2022-06-29 02:59:51

java回收機制的原理是什麼

垃圾回收是java與c/c++的最大不同。有了jvm的自動垃圾收集機制,就可以讓程序員專注於程序邏輯開發,而不是花費大量的時間是考慮變數應該在什麼時候去釋放。
首先我們要知道要,jvm是如何判斷一個對象已經變成了」垃圾「的呢?

一般用的是兩個方法:
1)引用記數法:
為每個對象保存一個引用的數量,每增加一個引用這個值就加1,每減少一個引用就減1.如果這個記數變為0了,就說明這個對象已經不再被使用了。那麼jvm就認為這個對象是可以回收的了。
但是這個方法有一個缺點,就是無法解決循環引用的問題。A引用B,B也引用A,如果A,B兩個對象都不再被使用了,那麼這兩個對象其實都是可以被回收的,但是他們的引用記數不為0.所以用這個辦法就沒有辦法回收了。
2)根搜索演算法
從一系列的」GC Roots「對象開始向下搜索,搜索走過的路徑稱為引用鏈。當一個對象到」GC Roots「之間沒有引用鏈時,被稱為引用不可達。引用不可到的對象被認為是可回收的對象。
java中可以當做為」GC Roots「對象的包括:
1:jvm虛擬機棧(棧幀中的局部變數表)中引用的對象
2:方法區中的類靜態屬性引用的對象
3:常量池中的常量引用的對象
4:本地方法棧JNI(native方法)中的引用的對象

② jvm的垃圾回收機制詳解

1.JVM的gc概述
gc即垃圾收集機制是指jvm用於釋放那些不再使用的對象所佔用的內存。java語言並不要求jvm有gc,也沒有規定gc如何工作。不過常用的jvm都有gc,而且大多數gc都使用類似的演算法管理內存和執行收集操作。
在充分理解了垃圾收集演算法和執行過程後,才能有效的優化它的性能。有些垃圾收集專用於特殊的應用程序。比如,實時應用程序主要是為了避免垃圾收集中斷,而大多數OLTP應用程序則注重整體效率。理解了應用程序的工作負荷和jvm支持的垃圾收集演算法,便可以進行優化配置垃圾收集器。
垃圾收集的目的在於清除不再使用的對象。gc通過確定對象是否被活動對象引用來確定是否收集該對象。gc首先要判斷該對象是否是時候可以收集。兩種常用的方法是引用計數和對象引用遍歷。
1.1.引用計數
引用計數存儲對特定對象的所有引用數,也就是說,當應用程序創建引用以及引用超出范圍時,jvm必須適當增減引用數。當某對象的引用數為0時,便可以進行垃圾收集。
1.2.對象引用遍歷
早期的jvm使用引用計數,現在大多數jvm採用對象引用遍歷。對象引用遍歷從一組對象開始,沿著整個對象圖上的每條鏈接,遞歸確定可到達(reachable)的對象。如果某對象不能從這些根對象的一個(至少一個)到達,則將它作為垃圾收集。在對象遍歷階段,gc必須記住哪些對象可以到達,以便刪除不可到達的對象,這稱為標記(marking)對象。
下一步,gc要刪除不可到達的對象。刪除時,有些gc只是簡單的掃描堆棧,刪除未標記的未標記的對象,並釋放它們的內存以生成新的對象,這叫做清除(sweeping)。這種方法的問題在於內存會分成好多小段,而它們不足以用於新的對象,但是組合起來卻很大。因此,許多gc可以重新組織內存中的對象,並進行壓縮(compact),形成可利用的空間。
為此,gc需要停止其他的活動活動。這種方法意味著所有與應用程序相關的工作停止,只有gc運行。結果,在響應期間增減了許多混雜請求。另外,更復雜的 gc不斷增加或同時運行以減少或者清除應用程序的中斷。有的gc使用單線程完成這項工作,有的則採用多線程以增加效率。
2.幾種垃圾回收機制
2.1.標記-清除收集器
這種收集器首先遍歷對象圖並標記可到達的對象,然後掃描堆棧以尋找未標記對象並釋放它們的內存。這種收集器一般使用單線程工作並停止其他操作。
2.2.標記-壓縮收集器
有時也叫標記-清除-壓縮收集器,與標記-清除收集器有相同的標記階段。在第二階段,則把標記對象復制到堆棧的新域中以便壓縮堆棧。這種收集器也停止其他操作。
2.3.復制收集器
這種收集器將堆棧分為兩個域,常稱為半空間。每次僅使用一半的空間,jvm生成的新對象則放在另一半空間中。gc運行時,它把可到達對象復制到另一半空間,從而壓縮了堆棧。這種方法適用於短生存期的對象,持續復制長生存期的對象則導致效率降低。
2.4.增量收集器
增量收集器把堆棧分為多個域,每次僅從一個域收集垃圾。這會造成較小的應用程序中斷。
2.5.分代收集器
這種收集器把堆棧分為兩個或多個域,用以存放不同壽命的對象。jvm生成的新對象一般放在其中的某個域中。過一段時間,繼續存在的對象將獲得使用期並轉入更長壽命的域中。分代收集器對不同的域使用不同的演算法以優化性能。
2.6.並發收集器
並發收集器與應用程序同時運行。這些收集器在某點上(比如壓縮時)一般都不得不停止其他操作以完成特定的任務,但是因為其他應用程序可進行其他的後台操作,所以中斷其他處理的實際時間大大降低。
2.7.並行收集器
並行收集器使用某種傳統的演算法並使用多線程並行的執行它們的工作。在多cpu機器上使用多線程技術可以顯著的提高java應用程序的可擴展性。

③ java有哪些垃圾回收演算法

System.gc是專門回收不用的對象的語法,當然你也可以自己寫函數來finalization()你的程序。一般JVM會根據虛擬內存佔用率來自動調用gc(garbage
collector),有時候即便你調用gc如果內存佔用不多回收處理工作也不會調用的,畢竟調用一次也要佔用資源。

④ JVM有哪些垃圾回收演算法

標記-清除,標記-復制,標記-整理

⑤ jvm垃圾回收是什麼時候觸發的垃圾回收演算法

1.垃圾回收目的:Java語言中一個顯著的特點就是引入了垃圾回收機制,使c++程序員最頭疼的內存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候不再需要考慮內存管理。由於有個垃圾回收機制,Java中的對象不再有「作用域」的概念,只有對象的引用才有「作用域」。垃圾回收可以有效的防止內存泄露,有效的使用空閑的內存。
ps:內存泄露是指該內存空間使用完畢之後未回收,在不涉及復雜數據結構的一般情況下,Java 的內存泄露表現為一個內存對象的生命周期超出了程序需要它的時間長度,我們有時也將其稱為「對象游離」。
2.
由於對象進行了分代處理,因此垃圾回收區域、時間也不一樣。GC有兩種類型:Scavenge GC和Full GC。
Scavenge GC
一般情況下,當新對象生成,並且在Eden申請空間失敗時,就會觸發Scavenge GC,對Eden區域進行GC,清除非存活對象,並且把尚且存活的對象移動到Survivor區。然後整理Survivor的兩個區。這種方式的GC是對年輕代的Eden區進行,不會影響到年老代。因為大部分對象都是從Eden區開始的,同時Eden區不會分配的很大,所以Eden區的GC會頻繁進行。因而,一般在這里需要使用速度快、效率高的演算法,使Eden去能盡快空閑出來。
Full GC
對整個堆進行整理,包括Young、Tenured和Perm。Full GC因為需要對整個堆進行回收,所以比Scavenge GC要慢,因此應該盡可能減少Full GC的次數。在對JVM調優的過程中,很大一部分工作就是對於FullGC的調節。有如下原因可能導致Full GC:
1.年老代(Tenured)被寫滿
2.持久代(Perm)被寫滿
3.System.gc()被顯示調用
4.上一次GC之後Heap的各域分配策略動態變化

⑥ java中的垃圾回收機制是怎樣的

java 的垃圾回收機制:
1.垃圾回收是由虛擬機自動執行,不能人為地干預。
2.系統比較空閑(垃圾回收線程)
3.對象不在被引用.對象處於引用的隔離島狀態(隔離引用),對象具備了回收的條件
4.gc()方法,可以建議虛擬機執行垃圾回收,但是不能確定是否會執行回收。

⑦ java 技術:jvm垃圾回收機制有哪些

深入理解Java虛擬機:JVM高級特性與最佳實踐

在《深入理解Java虛擬機:JVM高級特性與最佳實踐》,介紹了幾種垃圾回收演算法

  • Mark-Sweep(標記-清除)演算法

  • Copying(復制)演算法

  • Mark-Compact(標記-整理)演算法

  • Generational Collection(分代收集)演算法

和HotSpot虛擬機中的7種垃圾收集器:

  • Serial

  • ParNew

  • Parallel Scavenge、

  • Serial Old

  • Parallel Old

  • CMS

  • G1

⑧ JAVA垃圾收集的演算法是怎麼樣的

Java語言規范沒有明確地說明JVM使用哪種垃圾回收演算法,但是任何一種垃圾收集演算法一般要做2件基本的事情:(1)發現無用信息對象;(2)回收被無用對象佔用的內存空間,使該空間可被程序再次使用。 (課課家教育)

大多數垃圾回收演算法使用了根集(root set)這個概念;所謂根集就量正在執行的Java程序可以訪問的引用變數的集合(包括局部變數、參數、類變數),程序可以使用引用變數訪問對象的屬性和調用對象的方法。垃圾收集首選需要確定從根開始哪些是可達的和哪些是不可達的,從根集可達的對象都是活動對象,它們不能作為垃圾被回收,這也包括從根集間接可達的對象。而根集通過任意路徑不可達的對象符合垃圾收集的條件,應該被回收。下面介紹幾個常用的演算法。

1、 引用計數法(Reference Counting Collector)

引用計數法是唯一沒有使用根集的垃圾回收的法,該演算法使用引用計數器來區分存活對象和不再使用的對象。一般來說,堆中的每個對象對應一個引用計數器。當每一次創建一個對象並賦給一個變數時,引用計數器置為1。當對象被賦給任意變數時,引用計數器每次加1當對象出了作用域後(該對象丟棄不再使用),引用計數器減1,一旦引用計數器為0,對象就滿足了垃圾收集的條件。

基於引用計數器的垃圾收集器運行較快,不會長時間中斷程序執行,適宜地必須 實時運行的程序。但引用計數器增加了程序執行的開銷,因為每次對象賦給新的變數,計數器加1,而每次現有對象出了作用域生,計數器減1。

2、tracing演算法(Tracing Collector)

tracing演算法是為了解決引用計數法的問題而提出,它使用了根集的概念。基於tracing演算法的垃圾收集器從根集開始掃描,識別出哪些對象可達,哪些對象不可達,並用某種方式標記可達對象,例如對每個可達對象設置一個或多個位。在掃描識別過程中,基於tracing演算法的垃圾收集也稱為標記和清除(mark-and-sweep)垃圾收集器.

3、compacting演算法(Compacting Collector)

為了解決堆碎片問題,基於tracing的垃圾回收吸收了Compacting演算法的思想,在清除的過程中,演算法將所有的對象移到堆的一端,堆的另一端就變成了一個相鄰的空閑內存區,收集器會對它移動的所有對象的所有引用進行更新,使得這些引用在新的位置能識別原來 的對象。在基於Compacting演算法的收集器的實現中,一般增加句柄和句柄表。

4、ing演算法(Coping Collector)

該演算法的提出是為了克服句柄的開銷和解決堆碎片的垃圾回收。它開始時把堆分成 一個對象 面和多個空閑面, 程序從對象面為對象分配空間,當對象滿了,基於coping演算法的垃圾 收集就從根集中掃描活動對象,並將每個 活動對象復制到空閑面(使得活動對象所佔的內存之間沒有空閑洞),這樣空閑面變成了對象面,原來的對象面變成了空閑面,程序會在新的對象面中分配內存。

一種典型的基於coping演算法的垃圾回收是stop-and-演算法,它將堆分成對象面和空閑區域面,在對象面與空閑區域面的切換過程中,程序暫停執行。

5、generation演算法(Generational Collector)

stop-and-垃圾收集器的一個缺陷是收集器必須復制所有的活動對象,這增加了程序等待時間,這是coping演算法低效的原因。在程序設計中有這樣的規律:多數對象存在的時間比較短,少數的存在時間比較長。因此,generation演算法將堆分成兩個或多個,每個子堆作為對象的一代(generation)。由於多數對象存在的時間比較短,隨著程序丟棄不使用的對象,垃圾收集器將從最年輕的子堆中收集這些對象。在分代式的垃圾收集器運行後,上次運行存活下來的對象移到下一最高代的子堆中,由於老一代的子堆不會經常被回收,因而節省了時間。

6、adaptive演算法(Adaptive Collector)

在特定的情況下,一些垃圾收集演算法會優於其它演算法。基於Adaptive演算法的垃圾收集器就是監控當前堆的使用情況,並將選擇適當演算法的垃圾收集器。

⑨ jvm垃圾回收演算法有哪些

1.標記–清除演算法

執行步驟:

  • 標記:遍歷內存區域,對需要回收的對象打上標記。

  • 清除:再次遍歷內存,對已經標記過的內存進行回收。

2.復制演算法

將內存劃分為等大的兩塊,每次只使用其中的一塊。當一塊用完了,觸發GC時,將該塊中存活的對象復制到另一塊區域,然後一次性清理掉這塊沒有用的內存。下次觸發GC時將那塊中存活的的又復制到這塊,然後抹掉那塊,循環往復。

3. 標記–整理演算法

因為前面的復制演算法當對象的存活率比較高時,這樣一直復制過來,復制過去,沒啥意義,且浪費時間。所以針對老年代提出了「標記整理」演算法。

執行步驟:

  • 標記:對需要回收的進行標記

  • 整理:讓存活的對象,向內存的一端移動,然後直接清理掉沒有用的內存。

4. 分代收集演算法

當前大多商用虛擬機都採用這種分代收集演算法,這個演算法並沒有新的內容,只是根據對象的存活的時間的長短,將內存分為了新生代和老年代,這樣就可以針對不同的區域,採取對應的演算法。如:

  • 新生代,每次都有大量對象死亡,有老年代作為內存擔保,採取復制演算法。

  • 老年代,對象存活時間長,採用標記整理,或者標記清理演算法都可。

⑩ jvm的理解

1
JVM內存區域

我們在編寫程序時,經常會遇到OOM(out of Memory)以及內存泄漏等問題。為了避免出現這些問題,我們首先必須對JVM的內存劃分有個具體的認識。JVM將內存主要劃分為:方法區、虛擬機棧、本地方法棧、堆、程序計數器。JVM運行時數據區如下:

1.1
程序計數器
程序計數器是線程私有的區域,很好理解嘛~,每個線程當然得有個計數器記錄當前執行到那個指令。佔用的內存空間小,可以把它看成是當前線程所執行的位元組碼的行號指示器。如果線程在執行Java方法,這個計數器記錄的是正在執行的虛擬機位元組碼指令地址;如果執行的是Native方法,這個計數器的值為空(Undefined)。

此內存區域是唯一一個在Java虛擬機規范中沒有規定任何OutOfMemoryError情況的區域。

1.2
Java虛擬機棧
與程序計數器一樣,Java虛擬機棧也是線程私有的,其生命周期與線程相同。

如何理解虛擬機棧呢?

本質上來講,就是個棧。裡面存放的元素叫棧幀,棧幀好像很復雜的樣子,其實它很簡單!它裡面存放的是一個函數的上下文,具體存放的是執行的函數的一些數據。執行的函數需要的數據無非就是局部變數表(保存函數內部的變數)、操作數棧(執行引擎計算時需要),方法出口等等。

執行引擎每調用一個函數時,就為這個函數創建一個棧幀,並加入虛擬機棧。換個角度理解,每個函數從調用到執行結束,其實是對應一個棧幀的入棧和出棧。

注意這個區域可能出現的兩種異常:

一種是StackOverflowError,當前線程請求的棧深度大於虛擬機所允許的深度時,會拋出這個異常。製造這種異常很簡單:將一個函數反復遞歸自己,最終會出現棧溢出錯誤(StackOverflowError)。

另一種異常是OutOfMemoryError異常,當虛擬機棧可以動態擴展時(當前大部分虛擬機都可以),如果無法申請足夠多的內存就會拋出OutOfMemoryError,如何製作虛擬機棧OOM呢,參考一下代碼:

這段代碼有風險,可能會導致操作系統假死,請謹慎使用~~~

1.3
本地方法棧
本地方法棧與虛擬機所發揮的作用很相似,他們的區別在於虛擬機棧為執行Java代碼方法服務,而本地方法棧是為Native方法服務。與虛擬機棧一樣,本地方法棧也會拋出StackOverflowError和OutOfMemoryError異常。

1.4
Java堆
Java堆可以說是虛擬機中最大一塊內存了。它是所有線程所共享的內存區域,幾乎所有的實例對象都是在這塊區域中存放。當然,隨著JIT編譯器的發展,所有對象在堆上分配漸漸變得不那麼「絕對」了。

Java堆是垃圾收集器管理的主要區域。由於現在的收集器基本上採用的都是分代收集演算法,所有Java堆可以細分為:新生代和老年代。在細致分就是把新生代分為:Eden空間、From Survivor空間、To Survivor空間。當堆無法再擴展時,會拋出OutOfMemoryError異常。

1.5
方法區
方法區存放的是類信息、常量、靜態變數等。方法區是各個線程共享區域,很容易理解,我們在寫Java代碼時,每個線程度可以訪問同一個類的靜態變數對象。由於使用反射機制的原因,虛擬機很難推測那個類信息不再使用,因此這塊區域的回收很難。另外,對這塊區域主要是針對常量池回收,值得注意的是JDK1.7已經把常量池轉移到堆裡面了。同樣,當方法區無法滿足內存分配需求時,會拋出OutOfMemoryError。

製造方法區內存溢出,注意,必須在JDK1.6及之前版本才會導致方法區溢出,原因後面解釋,執行之前,可以把虛擬機的參數-XXpermSize和-XX:MaxPermSize限制方法區大小。

運行後會拋出java.lang.OutOfMemoryError:PermGen space異常。

解釋一下,String的intern()函數作用是如果當前的字元串在常量池中不存在,則放入到常量池中。上面的代碼不斷將字元串添加到常量池,最終肯定會導致內存不足,拋出方法區的OOM。

下面解釋一下,為什麼必須將上面的代碼在JDK1.6之前運行。我們前面提到,JDK1.7後,把常量池放入到堆空間中,這導致intern()函數的功能不同,具體怎麼個不同法,且看看下面代碼:

這段代碼在JDK1.6和JDK1.7運行的結果不同。

JDK1.6結果是:false,false ,JDK1.7結果是true, false。

原因是:JDK1.6中,intern()方法會吧首次遇到的字元串實例復制到常量池中,返回的也是常量池中的字元串的引用,而StringBuilder創建的字元串實例是在堆上面,所以必然不是同一個引用,返回false。

在JDK1.7中,intern不再復制實例,常量池中只保存首次出現的實例的引用,因此intern()返回的引用和由StringBuilder創建的字元串實例是同一個。為什麼對str2比較返回的是false呢?這是因為,JVM中內部在載入類的時候,就已經有"java"這個字元串,不符合「首次出現」的原則,因此返回false。

熱點內容
騰訊招聘php 發布:2024-04-25 15:17:02 瀏覽:444
雲伺服器多個公網ip搭建 發布:2024-04-25 15:13:15 瀏覽:845
phpmysqlupdate 發布:2024-04-25 15:08:15 瀏覽:253
隨時解壓 發布:2024-04-25 14:58:11 瀏覽:68
三率源碼 發布:2024-04-25 14:42:41 瀏覽:468
javastring轉string數組 發布:2024-04-25 14:42:10 瀏覽:137
飢荒如何更改密碼 發布:2024-04-25 14:42:02 瀏覽:744
百度雲如何解壓zip 發布:2024-04-25 14:38:57 瀏覽:571
母豬怎麼配置最好 發布:2024-04-25 14:35:47 瀏覽:76
php按鈕代碼 發布:2024-04-25 14:32:10 瀏覽:726