java中垃圾回收的代碼 java中垃圾回收的代碼是什么

java中的垃圾回收是什么意思?

垃圾回收就是gc(gabage collection)。

成都創(chuàng)新互聯(lián)公司擁有網(wǎng)站維護(hù)技術(shù)和項(xiàng)目管理團(tuán)隊(duì),建立的售前、實(shí)施和售后服務(wù)體系,為客戶提供定制化的成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、網(wǎng)站維護(hù)、綿陽(yáng)電信機(jī)房解決方案。為客戶網(wǎng)站安全和日常運(yùn)維提供整體管家式外包優(yōu)質(zhì)服務(wù)。我們的網(wǎng)站維護(hù)服務(wù)覆蓋集團(tuán)企業(yè)、上市公司、外企網(wǎng)站、商城開發(fā)、政府網(wǎng)站等各類型客戶群體,為全球成百上千家企業(yè)提供全方位網(wǎng)站維護(hù)、服務(wù)器維護(hù)解決方案。

java比c++的優(yōu)點(diǎn)就是多了垃圾回收機(jī)制,程序員不用去關(guān)心垃圾的回收,系統(tǒng)會(huì)自動(dòng)調(diào)用去回收內(nèi)存。

一般我們想回收的時(shí)候只需要調(diào)用system.gc方法就可以了。系統(tǒng)會(huì)自己去調(diào)用destroy方法和其他的回收方法釋放內(nèi)存,節(jié)省內(nèi)存空間。

垃圾回收目的:Java語(yǔ)言中一個(gè)顯著的特點(diǎn)就是引入了垃圾回收機(jī)制,使c++程序員最頭疼的內(nèi)存管理的問(wèn)題迎刃而解,它使得Java程序員在編寫程序的時(shí)候不再需要考慮內(nèi)存管理。

由于有個(gè)垃圾回收機(jī)制,Java中的對(duì)象不再有“作用域”的概念,只有對(duì)象的引用才有“作用域”。垃圾回收可以有效的防止內(nèi)存泄露,有效的使用空閑的內(nèi)存。

java垃圾回收問(wèn)題?

5分懸賞問(wèn)這么多問(wèn)題,真是服了!

不過(guò)還是回答你下.

JAVA的垃圾回收是自動(dòng)進(jìn)行的,非要手動(dòng)的話,System.gc()/Runtime.gc();

在多線程的情況下,此類可能不只產(chǎn)生1個(gè)實(shí)例;使用不同的類加載器加載就可以得到多個(gè)A的實(shí)例;

如果你的本意是想使類A只能有一個(gè)實(shí)例,那么請(qǐng)用Singleton模式改寫此類,你這個(gè)寫的看著有點(diǎn)難受.

計(jì)數(shù)器遞減沒有什么不可以的,不知道你的意圖,沒法搞.

java中是怎樣進(jìn)行垃圾回收的?

前面是我自己理解的后面是復(fù)制的

java中垃圾回收以前聽老師講好像是內(nèi)存滿了他才去做一次整體垃圾回收,在回收垃圾的同時(shí)會(huì)調(diào)用finalize方法.你在構(gòu)造一個(gè)類時(shí)可以構(gòu)造一個(gè)類時(shí)覆蓋他的finalize方法以便于該類在被垃圾回收時(shí)執(zhí)行一些代碼,比如釋放資源.

1.JVM的gc概述

gc即垃圾收集機(jī)制是指jvm用于釋放那些不再使用的對(duì)象所占用的內(nèi)存。java語(yǔ)言并不要求jvm有g(shù)c,也沒有規(guī)定gc如何工作。不過(guò)常用的jvm都有g(shù)c,而且大多數(shù)gc都使用類似的算法管理內(nèi)存和執(zhí)行收集操作。

在充分理解了垃圾收集算法和執(zhí)行過(guò)程后,才能有效的優(yōu)化它的性能。有些垃圾收集專用于特殊的應(yīng)用程序。比如,實(shí)時(shí)應(yīng)用程序主要是為了避免垃圾收集中斷,而大多數(shù)OLTP應(yīng)用程序則注重整體效率。理解了應(yīng)用程序的工作負(fù)荷和jvm支持的垃圾收集算法,便可以進(jìn)行優(yōu)化配置垃圾收集器。

垃圾收集的目的在于清除不再使用的對(duì)象。gc通過(guò)確定對(duì)象是否被活動(dòng)對(duì)象引用來(lái)確定是否收集該對(duì)象。gc首先要判斷該對(duì)象是否是時(shí)候可以收集。兩種常用的方法是引用計(jì)數(shù)和對(duì)象引用遍歷。

1.1.引用計(jì)數(shù)

引用計(jì)數(shù)存儲(chǔ)對(duì)特定對(duì)象的所有引用數(shù),也就是說(shuō),當(dāng)應(yīng)用程序創(chuàng)建引用以及引用超出范圍時(shí),jvm必須適當(dāng)增減引用數(shù)。當(dāng)某對(duì)象的引用數(shù)為0時(shí),便可以進(jìn)行垃圾收集。

1.2.對(duì)象引用遍歷

早期的jvm使用引用計(jì)數(shù),現(xiàn)在大多數(shù)jvm采用對(duì)象引用遍歷。對(duì)象引用遍歷從一組對(duì)象開始,沿著整個(gè)對(duì)象圖上的每條鏈接,遞歸確定可到達(dá)(reachable)的對(duì)象。如果某對(duì)象不能從這些根對(duì)象的一個(gè)(至少一個(gè))到達(dá),則將它作為垃圾收集。在對(duì)象遍歷階段,gc必須記住哪些對(duì)象可以到達(dá),以便刪除不可到達(dá)的對(duì)象,這稱為標(biāo)記(marking)對(duì)象。

下一步,gc要?jiǎng)h除不可到達(dá)的對(duì)象。刪除時(shí),有些gc只是簡(jiǎn)單的掃描堆棧,刪除未標(biāo)記的未標(biāo)記的對(duì)象,并釋放它們的內(nèi)存以生成新的對(duì)象,這叫做清除(sweeping)。這種方法的問(wèn)題在于內(nèi)存會(huì)分成好多小段,而它們不足以用于新的對(duì)象,但是組合起來(lái)卻很大。因此,許多gc可以重新組織內(nèi)存中的對(duì)象,并進(jìn)行壓縮(compact),形成可利用的空間。

為此,gc需要停止其他的活動(dòng)活動(dòng)。這種方法意味著所有與應(yīng)用程序相關(guān)的工作停止,只有g(shù)c運(yùn)行。結(jié)果,在響應(yīng)期間增減了許多混雜請(qǐng)求。另外,更復(fù)雜的 gc不斷增加或同時(shí)運(yùn)行以減少或者清除應(yīng)用程序的中斷。有的gc使用單線程完成這項(xiàng)工作,有的則采用多線程以增加效率。

2.幾種垃圾回收機(jī)制

2.1.標(biāo)記-清除收集器

這種收集器首先遍歷對(duì)象圖并標(biāo)記可到達(dá)的對(duì)象,然后掃描堆棧以尋找未標(biāo)記對(duì)象并釋放它們的內(nèi)存。這種收集器一般使用單線程工作并停止其他操作。

2.2.標(biāo)記-壓縮收集器

有時(shí)也叫標(biāo)記-清除-壓縮收集器,與標(biāo)記-清除收集器有相同的標(biāo)記階段。在第二階段,則把標(biāo)記對(duì)象復(fù)制到堆棧的新域中以便壓縮堆棧。這種收集器也停止其他操作。

2.3.復(fù)制收集器

這種收集器將堆棧分為兩個(gè)域,常稱為半空間。每次僅使用一半的空間,jvm生成的新對(duì)象則放在另一半空間中。gc運(yùn)行時(shí),它把可到達(dá)對(duì)象復(fù)制到另一半空間,從而壓縮了堆棧。這種方法適用于短生存期的對(duì)象,持續(xù)復(fù)制長(zhǎng)生存期的對(duì)象則導(dǎo)致效率降低。

2.4.增量收集器

增量收集器把堆棧分為多個(gè)域,每次僅從一個(gè)域收集垃圾。這會(huì)造成較小的應(yīng)用程序中斷。

2.5.分代收集器

這種收集器把堆棧分為兩個(gè)或多個(gè)域,用以存放不同壽命的對(duì)象。jvm生成的新對(duì)象一般放在其中的某個(gè)域中。過(guò)一段時(shí)間,繼續(xù)存在的對(duì)象將獲得使用期并轉(zhuǎn)入更長(zhǎng)壽命的域中。分代收集器對(duì)不同的域使用不同的算法以優(yōu)化性能。

2.6.并發(fā)收集器

并發(fā)收集器與應(yīng)用程序同時(shí)運(yùn)行。這些收集器在某點(diǎn)上(比如壓縮時(shí))一般都不得不停止其他操作以完成特定的任務(wù),但是因?yàn)槠渌麘?yīng)用程序可進(jìn)行其他的后臺(tái)操作,所以中斷其他處理的實(shí)際時(shí)間大大降低。

2.7.并行收集器

并行收集器使用某種傳統(tǒng)的算法并使用多線程并行的執(zhí)行它們的工作。在多cpu機(jī)器上使用多線程技術(shù)可以顯著的提高java應(yīng)用程序的可擴(kuò)展性。

3.Sun HotSpot

1.4.1 JVM堆大小的調(diào)整

Sun HotSpot 1.4.1使用分代收集器,它把堆分為三個(gè)主要的域:新域、舊域以及永久域。Jvm生成的所有新對(duì)象放在新域中。一旦對(duì)象經(jīng)歷了一定數(shù)量的垃圾收集循環(huán)后,便獲得使用期并進(jìn)入舊域。在永久域中jvm則存儲(chǔ)class和method對(duì)象。就配置而言,永久域是一個(gè)獨(dú)立域并且不認(rèn)為是堆的一部分。

下面介紹如何控制這些域的大小??墒褂?Xms和-Xmx 控制整個(gè)堆的原始大小或最大值。

下面的命令是把初始大小設(shè)置為128M:

java –Xms128m

–Xmx256m為控制新域的大小,可使用-XX:NewRatio設(shè)置新域在堆中所占的比例。

下面的命令把整個(gè)堆設(shè)置成128m,新域比率設(shè)置成3,即新域與舊域比例為1:3,新域?yàn)槎训?/4或32M:

java –Xms128m –Xmx128m

–XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize設(shè)置新域的初始值和最大值。

下面的命令把新域的初始值和最大值設(shè)置成64m:

java –Xms256m –Xmx256m –Xmn64m

永久域默認(rèn)大小為4m。運(yùn)行程序時(shí),jvm會(huì)調(diào)整永久域的大小以滿足需要。每次調(diào)整時(shí),jvm會(huì)對(duì)堆進(jìn)行一次完全的垃圾收集。

使用-XX:MaxPerSize標(biāo)志來(lái)增加永久域搭大小。在WebLogic Server應(yīng)用程序加載較多類時(shí),經(jīng)常需要增加永久域的最大值。當(dāng)jvm加載類時(shí),永久域中的對(duì)象急劇增加,從而使jvm不斷調(diào)整永久域大小。為了避免調(diào)整,可使用-XX:PerSize標(biāo)志設(shè)置初始值。

下面把永久域初始值設(shè)置成32m,最大值設(shè)置成64m。

java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m

默認(rèn)狀態(tài)下,HotSpot在新域中使用復(fù)制收集器。該域一般分為三個(gè)部分。第一部分為Eden,用于生成新的對(duì)象。另兩部分稱為救助空間,當(dāng)Eden 充滿時(shí),收集器停止應(yīng)用程序,把所有可到達(dá)對(duì)象復(fù)制到當(dāng)前的from救助空間,一旦當(dāng)前的from救助空間充滿,收集器則把可到達(dá)對(duì)象復(fù)制到當(dāng)前的to救助空間。From和to救助空間互換角色。維持活動(dòng)的對(duì)象將在救助空間不斷復(fù)制,直到它們獲得使用期并轉(zhuǎn)入舊域。使用-XX:SurvivorRatio 可控制新域子空間的大小。

同NewRation一樣,SurvivorRation規(guī)定某救助域與Eden空間的比值。比如,以下命令把新域設(shè)置成64m,Eden占32m,每個(gè)救助域各占16m:

java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2

如前所述,默認(rèn)狀態(tài)下HotSpot對(duì)新域使用復(fù)制收集器,對(duì)舊域使用標(biāo)記-清除-壓縮收集器。在新域中使用復(fù)制收集器有很多意義,因?yàn)閼?yīng)用程序生成的大部分對(duì)象是短壽命的。理想狀態(tài)下,所有過(guò)渡對(duì)象在移出Eden空間時(shí)將被收集。如果能夠這樣的話,并且移出Eden空間的對(duì)象是長(zhǎng)壽命的,那么理論上可以立即把它們移進(jìn)舊域,避免在救助空間反復(fù)復(fù)制。但是,應(yīng)用程序不能適合這種理想狀態(tài),因?yàn)樗鼈冇幸恍〔糠种虚L(zhǎng)壽命的對(duì)象。最好是保持這些中長(zhǎng)壽命的對(duì)象并放在新域中,因?yàn)閺?fù)制小部分的對(duì)象總比壓縮舊域廉價(jià)。為控制新域中對(duì)象的復(fù)制,可用-XX:TargetSurvivorRatio控制救助空間的比例(該值是設(shè)置救助空間的使用比例。如救助空間位1M,該值50表示可用500K)。該值是一個(gè)百分比,默認(rèn)值是50。當(dāng)較大的堆棧使用較低的 sruvivorratio時(shí),應(yīng)增加該值到80至90,以更好利用救助空間。用-XX:maxtenuring threshold可控制上限。

為放置所有的復(fù)制全部發(fā)生以及希望對(duì)象從eden擴(kuò)展到舊域,可以把MaxTenuring Threshold設(shè)置成0。設(shè)置完成后,實(shí)際上就不再使用救助空間了,因此應(yīng)把SurvivorRatio設(shè)成最大值以最大化Eden空間,設(shè)置如下:

java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatio=50000 …

4.BEA JRockit JVM的使用

Bea WebLogic 8.1使用的新的JVM用于Intel平臺(tái)。在Bea安裝完畢的目錄下可以看到有一個(gè)類似于jrockit81sp1_141_03的文件夾。這就是 Bea新JVM所在目錄。不同于HotSpot把Java字節(jié)碼編譯成本地碼,它預(yù)先編譯成類。JRockit還提供了更細(xì)致的功能用以觀察JVM的運(yùn)行狀態(tài),主要是獨(dú)立的GUI控制臺(tái)(只能適用于使用Jrockit才能使用jrockit81sp1_141_03自帶的console監(jiān)控一些cpu及 memory參數(shù))或者WebLogic Server控制臺(tái)。

Bea JRockit JVM支持4種垃圾收集器:

4.1.1.分代復(fù)制收集器

它與默認(rèn)的分代收集器工作策略類似。對(duì)象在新域中分配,即JRockit文檔中的nursery。這種收集器最適合單cpu機(jī)上小型堆操作。

4.1.2.單空間并發(fā)收集器

該收集器使用完整堆,并與背景線程共同工作。盡管這種收集器可以消除中斷,但是收集器需花費(fèi)較長(zhǎng)的時(shí)間尋找死對(duì)象,而且處理應(yīng)用程序時(shí)收集器經(jīng)常運(yùn)行。如果處理器不能應(yīng)付應(yīng)用程序產(chǎn)生的垃圾,它會(huì)中斷應(yīng)用程序并關(guān)閉收集。

分代并發(fā)收集器這種收集器在護(hù)理域使用排它復(fù)制收集器,在舊域中則使用并發(fā)收集器。由于它比單空間共同發(fā)生收集器中斷頻繁,因此它需要較少的內(nèi)存,應(yīng)用程序的運(yùn)行效率也較高,注意,過(guò)小的護(hù)理域可以導(dǎo)致大量的臨時(shí)對(duì)象被擴(kuò)展到舊域中。這會(huì)造成收集器超負(fù)荷運(yùn)作,甚至采用排它性工作方式完成收集。

4.1.3.并行收集器

該收集器也停止其他進(jìn)程的工作,但使用多線程以加速收集進(jìn)程。盡管它比其他的收集器易于引起長(zhǎng)時(shí)間的中斷,但一般能更好的利用內(nèi)存,程序效率也較高。

默認(rèn)狀態(tài)下,JRockit使用分代并發(fā)收集器。要改變收集器,可使用-Xgc:,對(duì)應(yīng)四個(gè)收集器分別為 gencopy,singlecon,gencon以及parallel。可使用-Xms和-Xmx設(shè)置堆的初始大小和最大值。要設(shè)置護(hù)理域,則使用- Xns:java –jrockit –Xms512m –Xmx512m –Xgc:gencon –Xns128m…盡管JRockit支持-verbose:gc開關(guān),但它輸出的信息會(huì)因收集器的不同而異。JRockit還支持memory、 load和codegen的輸出。

注意 :如果 使用JRockit JVM的話還可以使用WLS自帶的console(C:\bea\jrockit81sp1_141_03\bin下)來(lái)監(jiān)控一些數(shù)據(jù),如cpu, memery等。要想能構(gòu)監(jiān)控必須在啟動(dòng)服務(wù)時(shí)startWeblogic.cmd中加入-Xmanagement參數(shù)。

5.如何從JVM中獲取信息來(lái)進(jìn)行調(diào)整

-verbose.gc開關(guān)可顯示gc的操作內(nèi)容。打開它,可以顯示最忙和最空閑收集行為發(fā)生的時(shí)間、收集前后的內(nèi)存大小、收集需要的時(shí)間等。打開- xx:+ printgcdetails開關(guān),可以詳細(xì)了解gc中的變化。打開-XX: + PrintGCTimeStamps開關(guān),可以了解這些垃圾收集發(fā)生的時(shí)間,自jvm啟動(dòng)以后以秒計(jì)量。最后,通過(guò)-xx: + PrintHeapAtGC開關(guān)了解堆的更詳細(xì)的信息。為了了解新域的情況,可以通過(guò)-XX:=PrintTenuringDistribution開關(guān)了解獲得使用期的對(duì)象權(quán)。

6.Pdm系統(tǒng)JVM調(diào)整

6.1.服務(wù)器:前提內(nèi)存1G 單CPU

可通過(guò)如下參數(shù)進(jìn)行調(diào)整:-server 啟用服務(wù)器模式(如果CPU多,服務(wù)器機(jī)建議使用此項(xiàng))

-Xms,-Xmx一般設(shè)為同樣大小。 800m

-Xmn 是將NewSize與MaxNewSize設(shè)為一致。320m

-XX:PerSize 64m

-XX:NewSize 320m 此值設(shè)大可調(diào)大新對(duì)象區(qū),減少Full GC次數(shù)

-XX:MaxNewSize 320m

-XX:NewRato NewSize設(shè)了可不設(shè)。

-XX: SurvivorRatio

-XX:userParNewGC 可用來(lái)設(shè)置并行收集

-XX:ParallelGCThreads 可用來(lái)增加并行度

-XXUseParallelGC 設(shè)置后可以使用并行清除收集器

-XX:UseAdaptiveSizePolicy 與上面一個(gè)聯(lián)合使用效果更好,利用它可以自動(dòng)優(yōu)化新域大小以及救助空間比值

6.2.客戶機(jī):通過(guò)在JNLP文件中設(shè)置參數(shù)來(lái)調(diào)整客戶端JVM

JNLP中參數(shù):initial-heap-size和max-heap-size

這可以在framework的RequestManager中生成JNLP文件時(shí)加入上述參數(shù),但是這些值是要求根據(jù)客戶機(jī)的硬件狀態(tài)變化的(如客戶機(jī)的內(nèi)存大小等)。建議這兩個(gè)參數(shù)值設(shè)為客戶機(jī)可用內(nèi)存的60%(有待測(cè)試)。為了在動(dòng)態(tài)生成JNLP時(shí)以上兩個(gè)參數(shù)值能夠隨客戶機(jī)不同而不同,可靠慮獲得客戶機(jī)系統(tǒng)信息并將這些嵌到首頁(yè)index.jsp中作為連接請(qǐng)求的參數(shù)。

在設(shè)置了上述參數(shù)后可以通過(guò)Visualgc 來(lái)觀察垃圾回收的一些參數(shù)狀態(tài),再做相應(yīng)的調(diào)整來(lái)改善性能。一般的標(biāo)準(zhǔn)是減少fullgc的次數(shù),最好硬件支持使用并行垃圾回收(要求多CPU)。

Java垃圾回收怎么理解?

Java的堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),類的實(shí)例(對(duì)象)從中分配空間。Java虛擬機(jī)(JVM)的堆中儲(chǔ)存著正在運(yùn)行的應(yīng)用程序所建立的所有對(duì)象,這些對(duì)象通過(guò)new、newarray、anewarray和multianewarray等指令建立,但是它們不需要程序代碼來(lái)顯式地釋放。一般來(lái)說(shuō),堆的是由垃圾回收來(lái)負(fù)責(zé)的,盡管JVM規(guī)范并不要求特殊的垃圾回收技術(shù),甚至根本就不需要垃圾回收,但是由于內(nèi)存的有限性,JVM在實(shí)現(xiàn)的時(shí)候都有一個(gè)由垃圾回收所管理的堆。垃圾回收是一種動(dòng)態(tài)存儲(chǔ)管理技術(shù),它自動(dòng)地釋放不再被程序引用的對(duì)象,按照特定的垃圾收集算法來(lái)實(shí)現(xiàn)資源自動(dòng)回收的功能。

垃圾收集的意義

在C++中,對(duì)象所占的內(nèi)存在程序結(jié)束運(yùn)行之前一直被占用,在明確釋放之前不能分配給其它對(duì)象;而在Java中,當(dāng)沒有對(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í)上,除了釋放沒用的對(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)。首先,它能使編程效率提高。在沒有垃圾收集機(jī)制的時(shí)候,可能要花許多時(shí)間來(lái)解決一個(gè)難懂的存儲(chǔ)器問(wèn)題。在用Java語(yǔ)言編程的時(shí)候,靠垃圾收集機(jī)制可大大縮短時(shí)間。其次是它保護(hù)程序的完整性, 垃圾收集是Java語(yǔ)言安全性策略的一個(gè)重要部份。

垃圾收集的一個(gè)潛在的缺點(diǎn)是它的開銷影響程序性能。Java虛擬機(jī)必須追蹤運(yùn)行程序中有用的對(duì)象, 而且最終釋放沒用的對(duì)象。這一個(gè)過(guò)程需要花費(fèi)處理器的時(shí)間。其次垃圾收集算法的不完備性,早先采用的某些垃圾收集算法就不能保證100%收集到所有的廢棄內(nèi)存。當(dāng)然隨著垃圾收集算法的不斷改進(jìn)以及軟硬件運(yùn)行效率的不斷提升,這些問(wèn)題都可以迎刃而解。

垃圾收集的算法分析

Java語(yǔ)言規(guī)范沒有明確地說(shuō)明JVM使用哪種垃圾回收算法,但是任何一種垃圾收集算法一般要做2件基本的事情:(1)發(fā)現(xiàn)無(wú)用信息對(duì)象;(2)回收被無(wú)用對(duì)象占用的內(nèi)存空間,使該空間可被程序再次使用。

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

1、 引用計(jì)數(shù)法(Reference Counting Collector)

引用計(jì)數(shù)法是唯一沒有使用根集的垃圾回收的法,該算法使用引用計(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í)行的開銷,因?yàn)槊看螌?duì)象賦給新的變量,計(jì)數(shù)器加1,而每次現(xiàn)有對(duì)象出了作用域生,計(jì)數(shù)器減1。

2、tracing算法(Tracing Collector)

tracing算法是為了解決引用計(jì)數(shù)法的問(wèn)題而提出,它使用了根集的概念?;趖racing算法的垃圾收集器從根集開始掃描,識(shí)別出哪些對(duì)象可達(dá),哪些對(duì)象不可達(dá),并用某種方式標(biāo)記可達(dá)對(duì)象,例如對(duì)每個(gè)可達(dá)對(duì)象設(shè)置一個(gè)或多個(gè)位。在掃描識(shí)別過(guò)程中,基于tracing算法的垃圾收集也稱為標(biāo)記和清除(mark-and-sweep)垃圾收集器.

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)中,一般增加句柄和句柄表。

4、copying算法(Coping Collector)

該算法的提出是為了克服句柄的開銷和解決堆碎片的垃圾回收。它開始時(shí)把堆分成 一個(gè)對(duì)象 面和多個(gè)空閑面, 程序從對(duì)象面為對(duì)象分配空間,當(dāng)對(duì)象滿了,基于coping算法的垃圾 收集就從根集中掃描活動(dòng)對(duì)象,并將每個(gè) 活動(dòng)對(duì)象復(fù)制到空閑面(使得活動(dòng)對(duì)象所占的內(nèi)存之間沒有空閑洞),這樣空閑面變成了對(duì)象面,原來(lái)的對(duì)象面變成了空閑面,程序會(huì)在新的對(duì)象面中分配內(nèi)存。

一種典型的基于coping算法的垃圾回收是stop-and-copy算法,它將堆分成對(duì)象面和空閑區(qū)域面,在對(duì)象面與空閑區(qū)域面的切換過(guò)程中,程序暫停執(zhí)行。

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í)間。

6、adaptive算法(Adaptive Collector)

在特定的情況下,一些垃圾收集算法會(huì)優(yōu)于其它算法。基于Adaptive算法的垃圾收集器就是監(jiān)控當(dāng)前堆的使用情況,并將選擇適當(dāng)算法的垃圾收集器。

透視Java垃圾回收

1、命令行參數(shù)透視垃圾收集器的運(yùn)行

2、使用System.gc()可以不管JVM使用的是哪一種垃圾回收的算法,都可以請(qǐng)求Java的垃圾回收。

在命令行中有一個(gè)參數(shù)-verbosegc可以查看Java使用的堆內(nèi)存的情況,它的格式如下:

Java代碼 java -verbosegc classfile java -verbosegc classfile

可以看個(gè)例子:

Java代碼 class TestGC { public static void main(String[] args) /SPAN/li { new TestGC(); /SPAN/li System.gc(); System.runFinalization(); } } class TestGC { public static void main(String[] args) { new TestGC(); System.gc(); System.runFinalization(); } }

在這個(gè)例子中,一個(gè)新的對(duì)象被創(chuàng)建,由于它沒有使用,所以該對(duì)象迅速地變?yōu)榭蛇_(dá),程序編譯后,執(zhí)行命令: java -verbosegc TestGC 后結(jié)果為:

Java代碼 [Full GC 168K-97K(1984K), 0.0253873 secs] [Full GC 168K-97K(1984K), 0.0253873 secs]

機(jī)器的環(huán)境為,Windows 2000 + JDK1.3.1,箭頭前后的數(shù)據(jù)168K和97K分別表示垃圾收集GC前后所有存活對(duì)象使用的內(nèi)存容量,說(shuō)明有168K-97K=71K的對(duì)象容量被回收,括號(hào)內(nèi)的數(shù)據(jù)1984K為堆內(nèi)存的總?cè)萘?,收集所需要的時(shí)間是0.0253873秒(這個(gè)時(shí)間在每次執(zhí)行的時(shí)候會(huì)有所不同)。

2、finalize方法透視垃圾收集器的運(yùn)行

在JVM垃圾收集器收集一個(gè)對(duì)象之前 ,一般要求程序調(diào)用適當(dāng)?shù)姆椒ㄡ尫刨Y源,但在沒有明確釋放資源的情況下,Java提供了缺省機(jī)制來(lái)終止化該對(duì)象心釋放資源,這個(gè)方法就是finalize()。它的原型為:

Java代碼 protected void finalize() throws Throwable protected void finalize() throws Throwable

在finalize()方法返回之后,對(duì)象消失,垃圾收集開始執(zhí)行。原型中的throws Throwable表示它可以拋出任何類型的異常。

之所以要使用finalize(),是由于有時(shí)需要采取與Java的普通方法不同的一種方法,通過(guò)分配內(nèi)存來(lái)做一些具有C風(fēng)格的事情。這主要可以通過(guò)"固有方法"來(lái)進(jìn)行,它是從Java里調(diào)用非Java方法的一種方式。C和C++是目前唯一獲得固有方法支持的語(yǔ)言。但由于它們能調(diào)用通過(guò)其他語(yǔ)言編寫的子程序,所以能夠有效地調(diào)用任何東西。在非Java代碼內(nèi)部,也許能調(diào)用C的malloc()系列函數(shù),用它分配存儲(chǔ)空間。而且除非調(diào)用了free(),否則存儲(chǔ)空間不會(huì)得到釋放,從而造成內(nèi)存"漏洞"的出現(xiàn)。當(dāng)然,free()是一個(gè)C和C++函數(shù),所以我們需要在finalize()內(nèi)部的一個(gè)固有方法中調(diào)用它。也就是說(shuō)我們不能過(guò)多地使用finalize(),它并不是進(jìn)行普通清除工作的理想場(chǎng)所。

在普通的清除工作中,為清除一個(gè)對(duì)象,那個(gè)對(duì)象的用戶必須在希望進(jìn)行清除的地點(diǎn)調(diào)用一個(gè)清除方法。這與C++"破壞器"的概念稍有抵觸。在C++中,所有對(duì)象都會(huì)破壞(清除)。或者換句話說(shuō),所有對(duì)象都"應(yīng)該"破壞。若將C++對(duì)象創(chuàng)建成一個(gè)本地對(duì)象,比如在堆棧中創(chuàng)建(在Java中是不可能的),那么清除或破壞工作就會(huì)在"結(jié)束花括號(hào)"所代表的、創(chuàng)建這個(gè)對(duì)象的作用域的末尾進(jìn)行。若對(duì)象是用new創(chuàng)建的(類似于Java),那么當(dāng)程序員調(diào)用C++的delete命令時(shí)(Java沒有這個(gè)命令),就會(huì)調(diào)用相應(yīng)的破壞器。若程序員忘記了,那么永遠(yuǎn)不會(huì)調(diào)用破壞器,我們最終得到的將是一個(gè)內(nèi)存"漏洞",另外還包括對(duì)象的其他部分永遠(yuǎn)不會(huì)得到清除。

相反,Java不允許我們創(chuàng)建本地(局部)對(duì)象--無(wú)論如何都要使用new。但在Java中,沒有"delete"命令來(lái)釋放對(duì)象,因?yàn)槔占鲿?huì)幫助我們自動(dòng)釋放存儲(chǔ)空間。所以如果站在比較簡(jiǎn)化的立場(chǎng),我們可以說(shuō)正是由于存在垃圾收集機(jī)制,所以Java沒有破壞器。然而,隨著以后學(xué)習(xí)的深入,就會(huì)知道垃圾收集器的存在并不能完全消除對(duì)破壞器的需要,或者說(shuō)不能消除對(duì)破壞器代表的那種機(jī)制的需要(而且絕對(duì)不能直接調(diào)用finalize(),所以應(yīng)盡量避免用它)。若希望執(zhí)行除釋放存儲(chǔ)空間之外的其他某種形式的清除工作,仍然必須調(diào)用Java中的一個(gè)方法。它等價(jià)于C++的破壞器,只是沒后者方便。

關(guān)于垃圾收集的幾點(diǎn)補(bǔ)充

經(jīng)過(guò)上述的說(shuō)明,可以發(fā)現(xiàn)垃圾回收有以下的幾個(gè)特點(diǎn):

(1)垃圾收集發(fā)生的不可預(yù)知性:由于實(shí)現(xiàn)了不同的垃圾收集算法和采用了不同的收集機(jī)制,所以它有可能是定時(shí)發(fā)生,有可能是當(dāng)出現(xiàn)系統(tǒng)空閑CPU資源時(shí)發(fā)生,也有可能是和原始的垃圾收集一樣,等到內(nèi)存消耗出現(xiàn)極限時(shí)發(fā)生,這與垃圾收集器的選擇和具體的設(shè)置都有關(guān)系。

(2)垃圾收集的精確性:主要包括2 個(gè)方面:(a)垃圾收集器能夠精確標(biāo)記活著的對(duì)象;(b)垃圾收集器能夠精確地定位對(duì)象之間的引用關(guān)系。前者是完全地回收所有廢棄對(duì)象的前提,否則就可能造成內(nèi)存泄漏。而后者則是實(shí)現(xiàn)歸并和復(fù)制等算法的必要條件。所有不可達(dá)對(duì)象都能夠可靠地得到回收,所有對(duì)象都能夠重新分配,允許對(duì)象的復(fù)制和對(duì)象內(nèi)存的縮并,這樣就有效地防止內(nèi)存的支離破碎。

(3)現(xiàn)在有許多種不同的垃圾收集器,每種有其算法且其表現(xiàn)各異,既有當(dāng)垃圾收集開始時(shí)就停止應(yīng)用程序的運(yùn)行,又有當(dāng)垃圾收集開始時(shí)也允許應(yīng)用程序的線程運(yùn)行,還有在同一時(shí)間垃圾收集多線程運(yùn)行。

(4)垃圾收集的實(shí)現(xiàn)和具體的JVM 以及JVM的內(nèi)存模型有非常緊密的關(guān)系。不同的JVM 可能采用不同的垃圾收集,而JVM 的內(nèi)存模型決定著該JVM可以采用哪些類型垃圾收集?,F(xiàn)在,HotSpot 系列JVM中的內(nèi)存系統(tǒng)都采用先進(jìn)的面向?qū)ο蟮目蚣茉O(shè)計(jì),這使得該系列JVM都可以采用最先進(jìn)的垃圾收集。

(5)隨著技術(shù)的發(fā)展,現(xiàn)代垃圾收集技術(shù)提供許多可選的垃圾收集器,而且在配置每種收集器的時(shí)候又可以設(shè)置不同的參數(shù),這就使得根據(jù)不同的應(yīng)用環(huán)境獲得最優(yōu)的應(yīng)用性能成為可能。

針對(duì)以上特點(diǎn),我們?cè)谑褂玫臅r(shí)候要注意:

(1)不要試圖去假定垃圾收集發(fā)生的時(shí)間,這一切都是未知的。比如,方法中的一個(gè)臨時(shí)對(duì)象在方法調(diào)用完畢后就變成了無(wú)用對(duì)象,這個(gè)時(shí)候它的內(nèi)存就可以被釋放。

(2)Java中提供了一些和垃圾收集打交道的類,而且提供了一種強(qiáng)行執(zhí)行垃圾收集的方法--調(diào)用System.gc(),但這同樣是個(gè)不確定的方法。Java 中并不保證每次調(diào)用該方法就一定能夠啟動(dòng)垃圾收集,它只不過(guò)會(huì)向JVM發(fā)出這樣一個(gè)申請(qǐng),到底是否真正執(zhí)行垃圾收集,一切都是個(gè)未知數(shù)。

(3)挑選適合自己的垃圾收集器。一般來(lái)說(shuō),如果系統(tǒng)沒有特殊和苛刻的性能要求,可以采用JVM的缺省選項(xiàng)。否則可以考慮使用有針對(duì)性的垃圾收集器,比如增量收集器就比較適合實(shí)時(shí)性要求較高的系統(tǒng)之中。系統(tǒng)具有較高的配置,有比較多的閑置資源,可以考慮使用并行標(biāo)記/清除收集器。

(4)關(guān)鍵的也是難把握的問(wèn)題是內(nèi)存泄漏。良好的編程習(xí)慣和嚴(yán)謹(jǐn)?shù)木幊虘B(tài)度永遠(yuǎn)是最重要的,不要讓自己的一個(gè)小錯(cuò)誤導(dǎo)致內(nèi)存出現(xiàn)大漏洞。

(5)盡早釋放無(wú)用對(duì)象的引用。大多數(shù)程序員在使用臨時(shí)變量的時(shí)候,都是讓引用變量在退出活動(dòng)域(scope)后,自動(dòng)設(shè)置為null,暗示垃圾收集器來(lái)收集該對(duì)象,還必須注意該引用的對(duì)象是否被監(jiān)聽,如果有,則要去掉監(jiān)聽器,然后再賦空值。

結(jié)束語(yǔ)

一般來(lái)說(shuō),Java開發(fā)人員可以不重視JVM中堆內(nèi)存的分配和垃圾處理收集,但是,充分理解Java的這一特性可以讓我們更有效地利用資源。同時(shí)要注意finalize()方法是Java的缺省機(jī)制,有時(shí)為確保對(duì)象資源的明確釋放,可以編寫自己的finalize方法

關(guān)于java垃圾回收,不懂?

垃圾回收機(jī)制是JAVA一個(gè)清理自動(dòng)內(nèi)存的機(jī)制。就是把沒用的對(duì)象清理出內(nèi)存。

因?yàn)樗且粋€(gè)自動(dòng)的過(guò)程,所有我們不需要手動(dòng)清理了,當(dāng)然,我們也不能控制它的執(zhí)行。

給你舉個(gè)例子,大街上好多垃圾桶,只要是你把垃圾扔里面了,就會(huì)有人來(lái)清理,當(dāng)然,人什么時(shí)候清理你管不著。

java垃圾回收的問(wèn)題

javaGC是這樣的,當(dāng)一個(gè)對(duì)象沒有引用指向它時(shí),就成為了垃圾,就會(huì)被GC回收。在第四行中,對(duì)象new StringBuffer("HI");又多了一個(gè)名字sf_arr[0],所以當(dāng)sf=null并不能保證不再有引用指向它。

舉個(gè)例子:小明這個(gè)人,如果沒有名字就會(huì)死掉,現(xiàn)在我給小明再取個(gè)名字小華,那么他就有兩個(gè)名字了,即使小明這個(gè)名字不用了,他依然還是有名字的。只有當(dāng)小華也不用了,這個(gè)人才是真正沒有的名字的。

從以上代碼來(lái)看,應(yīng)該是第六行成為gc對(duì)象。

網(wǎng)站題目:java中垃圾回收的代碼 java中垃圾回收的代碼是什么
分享地址:http://muchs.cn/article12/hphegc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、建站公司用戶體驗(yàn)、全網(wǎng)營(yíng)銷推廣、域名注冊(cè)、網(wǎng)站導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化