Java垃圾收集学习笔记
(1)除了釋放不再被引用的對(duì)象,垃圾收集器還要處理堆碎塊。請(qǐng)求分配新對(duì)象時(shí)可能不得不增大堆空間的大小,雖然可以使用的空閑空間是足夠的,但是堆中沒有沒有連續(xù)的空間放得下新對(duì)象。可能會(huì)導(dǎo)致虛擬機(jī)產(chǎn)生不必要的”內(nèi)存不足“錯(cuò)誤。
(2)使用垃圾收集堆,有一個(gè)潛在的缺陷就是加大程序的負(fù)擔(dān),可能影響程序的性能。因?yàn)樘摂M機(jī)需要追蹤哪些對(duì)象被正在執(zhí)行的程序引用,還要?jiǎng)討B(tài)釋放垃圾對(duì)象。
(3)程序可以調(diào)用System.gc()建議jvm去收集垃圾, 但是不能為垃圾回收機(jī)制指定某個(gè)對(duì)象是不是垃圾。即便調(diào)用了gc(),并不會(huì)馬上進(jìn)行垃圾回收,甚至不一定會(huì)執(zhí)行垃圾回收。所有的內(nèi)存分配和回收權(quán)限都在jvm,不在開發(fā)人員手里。
可以試試:
public class RubbishRelease {// 類的finalize方法,可以告訴垃圾回收器應(yīng)該執(zhí)行的操作,該方法從Object類繼承而來。// 在從堆中永久刪除對(duì)象之前,垃圾回收器調(diào)用該對(duì)象的finalize方法。public void finalize() {System.out.println("the Object is going...");}public static void main(String[] args) {for (int i = 0; i < 100; i++) {// 下面不斷創(chuàng)建對(duì)象,但是這些對(duì)象都沒有被引用new RubbishRelease();new RubbishRelease();new RubbishRelease();System.gc();}System.out.println("The program is over!");} }運(yùn)行結(jié)果:
(4)垃圾收集算法有很多,但任何垃圾收集算法都必須做兩件事情。首先,它必須檢測(cè)出垃圾對(duì)象。其次,它必須回收垃圾對(duì)象所使用的堆空間并還給程序。
(5)區(qū)分活動(dòng)對(duì)象和垃圾的兩個(gè)基本方法是引用計(jì)數(shù)和跟蹤。
(6)引用計(jì)數(shù)是垃圾收集的早期策略。在這種方法中,堆中每一個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù)。一個(gè)對(duì)象被創(chuàng)建了,并且指向該對(duì)象的引用被分配給一個(gè)變量,這個(gè)對(duì)象的引用計(jì)數(shù)被置為1。當(dāng)任何其他變量被賦值為對(duì)這個(gè)對(duì)象的引用時(shí),計(jì)數(shù)加1。當(dāng)一個(gè)對(duì)象的引用超過了生存期或者被設(shè)置一個(gè)新的值時(shí),對(duì)象的引用計(jì)數(shù)減1。任何引用計(jì)數(shù)為0的對(duì)象可以被當(dāng)作垃圾收集。當(dāng)一個(gè)對(duì)象被垃圾收集的時(shí)候,它引用的任何對(duì)象計(jì)數(shù)值減1。這種方法的好處是,引用計(jì)數(shù)收集器可以很快地執(zhí)行,交織在程序的運(yùn)行之中。這個(gè)特性對(duì)于程序不能被長(zhǎng)時(shí)間打斷的實(shí)時(shí)環(huán)境很有利。壞處就是,引用計(jì)數(shù)無法檢測(cè)出循環(huán)(即兩個(gè)或者更多的對(duì)象互相引用)。
(7)跟蹤收集器追蹤從根節(jié)點(diǎn)開始的對(duì)象引用圖。給追蹤過程中遇到對(duì)象以某種方式打上標(biāo)記。追蹤結(jié)束時(shí),未被標(biāo)記的對(duì)象就是無法觸及的,從而被收集。基本的追蹤算法被稱作“標(biāo)記并清除”,這個(gè)名字指出垃圾收集過程的兩個(gè)階段。
(8)Java虛擬機(jī)的垃圾收集器可能有對(duì)付堆碎塊的策略。標(biāo)記并清除收集器通常使用的兩種策略是壓縮和拷貝。這兩種方法都是快速地移動(dòng)對(duì)象來減少堆碎塊。
(9)壓縮收集器把活動(dòng)的對(duì)象越過空閑區(qū)滑動(dòng)到堆的一端,在這個(gè)過程中,堆的另一端出現(xiàn)一個(gè)大的連續(xù)空閑區(qū)。所有被移動(dòng)的對(duì)象的引用也被更新,指向新的位置。
(10)拷貝收集器把所有的活動(dòng)的對(duì)象移動(dòng)到一個(gè)新的區(qū)域。在拷貝過程中,被緊挨著布置,這樣可以消除原本它們?cè)谂f區(qū)域的空隙。即空閑區(qū)。一般的拷貝收集器算法被稱為“停止并拷貝”。此方案中,堆被分成兩個(gè)區(qū)域,任何時(shí)候都使用一個(gè)區(qū)域。對(duì)象在同一個(gè)區(qū)域中分配直到被耗盡。此時(shí),程序執(zhí)行被中止,堆被遍歷,遍歷時(shí)遇到活動(dòng)的對(duì)象被拷貝到另個(gè)區(qū)域。當(dāng)停止和拷貝過程結(jié)束時(shí),程序恢復(fù)執(zhí)行。依次往復(fù),對(duì)于指定大小的堆來說需要兩倍大小的內(nèi)存,由于任何時(shí)候都只使用其中的一半,這就是該方法帶來的代價(jià)。
(11)按代收集:根據(jù)對(duì)象的存活周期(一次垃圾收集為一個(gè)周期)的不同將內(nèi)存劃分為幾塊。一般是把Java堆分為新生代和老年代,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴āT谛律?#xff0c;每次垃圾收集時(shí)都發(fā)現(xiàn)有大批對(duì)象死去,只有少量存活,那就選用拷貝算法,只需要付出少量存活對(duì)象的拷貝成本就可以完成收集。而老年代中因?yàn)閷?duì)象存活率高、沒有額外空間對(duì)它進(jìn)行分配擔(dān)保,可以使用“標(biāo)記并清除”算法。
(12)終結(jié)方法(finalize),這個(gè)在上面第3點(diǎn)也有提到:這個(gè)方法是垃圾收集器在釋放對(duì)象前必須運(yùn)行。這個(gè)可能存在的終結(jié)方法使得任何Java虛擬機(jī)的垃圾收集器要完成的工作更加復(fù)雜。因?yàn)榻K結(jié)方法可能“復(fù)活”了某些不再被引用的對(duì)象(本身或者其他對(duì)象)。
(13)堆中的每一個(gè)對(duì)象都有三種狀態(tài)之一:可觸及的、可復(fù)活的以及不可觸及的。可觸及狀態(tài)好理解。關(guān)于可復(fù)活狀態(tài):它在從根節(jié)點(diǎn)開始的追蹤圖中不可觸及,但是又可能在垃圾收集器執(zhí)行某些終結(jié)方法時(shí)觸及。不僅僅是那些聲明了finalize方法的對(duì)象,而是所有的對(duì)象都要經(jīng)過可復(fù)活狀態(tài)。而不可觸及狀態(tài)標(biāo)志著不但對(duì)象不再被觸及,而且也不可能通過任何終結(jié)方法復(fù)活。不可觸及的對(duì)象不再對(duì)程序的執(zhí)行產(chǎn)生影響,可自由地回收它們占據(jù)的內(nèi)存。
(14)對(duì)象的強(qiáng),軟,弱,虛引用。
強(qiáng)引用:如果一個(gè)對(duì)象具有強(qiáng)引用,垃圾回收器絕不會(huì)回收它。當(dāng)內(nèi)存空間不足,JVM寧愿拋出OutOfMemoryError錯(cuò)誤,使程序異常終止,也不會(huì)考隨意回收具有強(qiáng)引用的對(duì)象來解決內(nèi)存不足的問題。
軟引用:如果一個(gè)對(duì)象具有軟引用。如果內(nèi)存空間足夠。垃圾回收器不會(huì)回收它。如果內(nèi)存不足了,就會(huì)回收這些對(duì)象的內(nèi)存。只要垃圾回收器沒有回收它,該對(duì)象就可以被程序使用。軟引用可用來實(shí)現(xiàn)內(nèi)存敏感的高速緩存。
弱引用:如果一個(gè)對(duì)象具有弱引用。當(dāng)垃圾回收器發(fā)現(xiàn)只具有弱引用對(duì)象,不管當(dāng)前內(nèi)存空間足夠與否,都會(huì)回收它的內(nèi)存。不過,由于垃圾回收器是一個(gè)優(yōu)先級(jí)很低的線程,因此不一定會(huì)很快發(fā)現(xiàn)只具有弱引用的對(duì)象。
虛引用:虛引用不會(huì)決定對(duì)象的生命周期。如果一個(gè)對(duì)象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時(shí)候都可能被垃圾回收器回收。
總結(jié)
以上是生活随笔為你收集整理的Java垃圾收集学习笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 寻迹小车开发日记
- 下一篇: Java摇骰子比大小_android 摇