新聞中心
創(chuàng)新互聯(lián)www.cdcxhl.cn八線動(dòng)態(tài)BGP香港云服務(wù)器提供商,新人活動(dòng)買(mǎi)多久送多久,劃算不套路!
1. 垃圾回收的意義
在C++中,對(duì)象所占的內(nèi)存在程序結(jié)束運(yùn)行之前一直被占用,在明確釋放之前不能分配給其它對(duì)象;而在Java中,當(dāng)沒(méi)有對(duì)象引用指向原先分配給某個(gè)對(duì)象的內(nèi)存時(shí),該內(nèi)存便成為垃圾。JVM的一個(gè)系統(tǒng)級(jí)線程會(huì)自動(dòng)釋放該內(nèi)存塊。垃圾回收意味著程序不再需要的對(duì)象是"無(wú)用信息",這些信息將被丟棄。當(dāng)一個(gè)對(duì)象不再被引用的時(shí)候,內(nèi)存回收它占領(lǐng)的空間,以便空間被后來(lái)的新對(duì)象使用。事實(shí)上,除了釋放沒(méi)用的對(duì)象,垃圾回收也可以清除內(nèi)存記錄碎片。由于創(chuàng)建對(duì)象和垃圾回收器釋放丟棄對(duì)象所占的內(nèi)存空間,內(nèi)存會(huì)出現(xiàn)碎片。碎片是分配給對(duì)象的內(nèi)存塊之間的空閑內(nèi)存洞。碎片整理將所占用的堆內(nèi)存移到堆的一端,JVM將整理出的內(nèi)存分配給新的對(duì)象。
垃圾回收能自動(dòng)釋放內(nèi)存空間,減輕編程的負(fù)擔(dān)。這使Java 虛擬機(jī)具有一些優(yōu)點(diǎn)。首先,它能使編程效率提高。在沒(méi)有垃圾回收機(jī)制的時(shí)候,可能要花許多時(shí)間來(lái)解決一個(gè)難懂的存儲(chǔ)器問(wèn)題。在用Java語(yǔ)言編程的時(shí)候,靠垃圾回收機(jī)制可大大縮短時(shí)間。其次是它保護(hù)程序的完整性, 垃圾回收是Java語(yǔ)言安全性策略的一個(gè)重要部份。
垃圾回收的一個(gè)潛在的缺點(diǎn)是它的開(kāi)銷(xiāo)影響程序性能。Java虛擬機(jī)必須追蹤運(yùn)行程序中有用的對(duì)象,而且最終釋放沒(méi)用的對(duì)象。這一個(gè)過(guò)程需要花費(fèi)處理器的時(shí)間。其次垃圾回收算法的不完備性,早先采用的某些垃圾回收算法就不能保證100%收集到所有的廢棄內(nèi)存。當(dāng)然隨著垃圾回收算法的不斷改進(jìn)以及軟硬件運(yùn)行效率的不斷提升,這些問(wèn)題都可以迎刃而解。
2. 垃圾收集的算法分析
Java語(yǔ)言規(guī)范沒(méi)有明確地說(shuō)明JVM使用哪種垃圾回收算法,但是任何一種垃圾回收算法一般要做2件基本的事情:
(1)發(fā)現(xiàn)無(wú)用信息對(duì)象;
(2)回收被無(wú)用對(duì)象占用的內(nèi)存空間,使該空間可被程序再次使用。
大多數(shù)垃圾回收算法使用了根集(root set)這個(gè)概念;所謂根集就是正在執(zhí)行的Java程序可以訪問(wèn)的引用變量的集合(包括局部變量、參數(shù)、類(lèi)變量),程序可以使用引用變量訪問(wèn)對(duì)象的屬性和調(diào)用對(duì)象的方法。垃圾回收首先需要確定從根開(kāi)始哪些是可達(dá)的和哪些是不可達(dá)的,從根集可達(dá)的對(duì)象都是活動(dòng)對(duì)象,它們不能作為垃圾被回收,這也包括從根集間接可達(dá)的對(duì)象。而根集通過(guò)任意路徑不可達(dá)的對(duì)象符合垃圾收集的條件,應(yīng)該被回收。下面介紹幾個(gè)常用的算法。
2.1. 引用計(jì)數(shù)法(Reference Counting Collector)
引用計(jì)數(shù)法是唯一沒(méi)有使用根集的垃圾回收的法,該算法使用引用計(jì)數(shù)器來(lái)區(qū)分存活對(duì)象和不再使用的對(duì)象。一般來(lái)說(shuō),堆中的每個(gè)對(duì)象對(duì)應(yīng)一個(gè)引用計(jì)數(shù)器。當(dāng)每一次創(chuàng)建一個(gè)對(duì)象并賦給一個(gè)變量時(shí),引用計(jì)數(shù)器置為1。當(dāng)對(duì)象被賦給任意變量時(shí),引用計(jì)數(shù)器每次加1當(dāng)對(duì)象出了作用域后(該對(duì)象丟棄不再使用),引用計(jì)數(shù)器減1,一旦引用計(jì)數(shù)器為0,對(duì)象就滿足了垃圾收集的條件。
基于引用計(jì)數(shù)器的垃圾收集器運(yùn)行較快,不會(huì)長(zhǎng)時(shí)間中斷程序執(zhí)行,適宜地必須實(shí)時(shí)運(yùn)行的程序。但引用計(jì)數(shù)器增加了程序執(zhí)行的開(kāi)銷(xiāo),因?yàn)槊看螌?duì)象賦給新的變量,計(jì)數(shù)器加1,而每次現(xiàn)有對(duì)象出了作用域生,計(jì)數(shù)器減1。
2.2. tracing算法(Tracing Collector)
tracing算法是為了解決引用計(jì)數(shù)法的問(wèn)題而提出,它使用了根集的概念?;趖racing算法的垃圾收集器從根集開(kāi)始掃描,識(shí)別出哪些對(duì)象可達(dá),哪些對(duì)象不可達(dá),并用某種方式標(biāo)記可達(dá)對(duì)象,例如對(duì)每個(gè)可達(dá)對(duì)象設(shè)置一個(gè)或多個(gè)位。在掃描識(shí)別過(guò)程中,基于tracing算法的垃圾收集也稱(chēng)為標(biāo)記和清除(mark-and-sweep)垃圾收集器.
2.3. compacting算法(Compacting Collector)
為了解決堆碎片問(wèn)題,基于tracing的垃圾回收吸收了Compacting算法的思想,在清除的過(guò)程中,算法將所有的對(duì)象移到堆的一端,堆的另一端就變成了一個(gè)相鄰的空閑內(nèi)存區(qū),收集器會(huì)對(duì)它移動(dòng)的所有對(duì)象的所有引用進(jìn)行更新,使得這些引用在新的位置能識(shí)別原來(lái)的對(duì)象。在基于Compacting算法的收集器的實(shí)現(xiàn)中,一般增加句柄和句柄表。
2.4. copying算法(Coping Collector)
該算法的提出是為了克服句柄的開(kāi)銷(xiāo)和解決堆碎片的垃圾回收。它開(kāi)始時(shí)把堆分成一個(gè)對(duì)象區(qū)和多個(gè)空閑區(qū),程序從對(duì)象區(qū)為對(duì)象分配空間,當(dāng)對(duì)象滿了,基于coping算法的垃圾回收就從根集中掃描活動(dòng)對(duì)象,并將每個(gè)活動(dòng)對(duì)象復(fù)制到空閑區(qū)(使得活動(dòng)對(duì)象所占的內(nèi)存之間沒(méi)有空閑間隔),這樣空閑區(qū)變成了對(duì)象區(qū),原來(lái)的對(duì)象區(qū)變成了空閑區(qū),程序會(huì)在新的對(duì)象區(qū)中分配內(nèi)存。
一種典型的基于coping算法的垃圾回收是stop-and-copy算法,它將堆分成對(duì)象區(qū)和空閑區(qū)域區(qū),在對(duì)象區(qū)與空閑區(qū)域的切換過(guò)程中,程序暫停執(zhí)行。
2.5. generation算法(Generational Collector)
stop-and-copy垃圾收集器的一個(gè)缺陷是收集器必須復(fù)制所有的活動(dòng)對(duì)象,這增加了程序等待時(shí)間,這是coping算法低效的原因。在程序設(shè)計(jì)中有這樣的規(guī)律:多數(shù)對(duì)象存在的時(shí)間比較短,少數(shù)的存在時(shí)間比較長(zhǎng)。因此,generation算法將堆分成兩個(gè)或多個(gè),每個(gè)子堆作為對(duì)象的一代 (generation)。由于多數(shù)對(duì)象存在的時(shí)間比較短,隨著程序丟棄不使用的對(duì)象,垃圾收集器將從最年輕的子堆中收集這些對(duì)象。在分代式的垃圾收集器運(yùn)行后,上次運(yùn)行存活下來(lái)的對(duì)象移到下一最高代的子堆中,由于老一代的子堆不會(huì)經(jīng)常被回收,因而節(jié)省了時(shí)間。
2.6. adaptive算法(Adaptive Collector)
在特定的情況下,一些垃圾收集算法會(huì)優(yōu)于其它算法?;贏daptive算法的垃圾收集器就是監(jiān)控當(dāng)前堆的使用情況,并將選擇適當(dāng)算法的垃圾收集器。
3. System.gc()方法
命令行參數(shù)透視垃圾收集器的運(yùn)行
使用System.gc()可以不管JVM使用的是哪一種垃圾回收的算法,都可以請(qǐng)求Java的垃圾回收。在命令行中有一個(gè)參數(shù)-verbosegc可以查看Java使用的堆內(nèi)存的情況,它的格式如下:
java -verbosegc classfile
可以看個(gè)例子:
class TestGC { public static void main(String[] args) { new TestGC(); System.gc(); System.runFinalization(); } }
分享標(biāo)題:Java垃圾回收機(jī)制詳解(動(dòng)力節(jié)點(diǎn)Java學(xué)院整理)-創(chuàng)新互聯(lián)
文章位置:http://www.dlmjj.cn/article/dcdhcs.html