麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Java堆的管理--透視垃圾回收機(jī)制

2019-11-18 13:16:37
字體:
供稿:網(wǎng)友

  1 引言
  java的堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),類的實(shí)例(對(duì)象)從中分配空間。Java虛擬機(jī)(JVM)的堆中儲(chǔ)存著正在運(yùn)行的應(yīng)用程序所建立的所有對(duì)象,這些對(duì)象通過new、newarray、anewarray和multianewarray等指令建立,但是它們不需要程序代碼來顯式地釋放。一般來說,堆的是由垃圾回收 來負(fù)責(zé)的,盡管JVM規(guī)范并不要求非凡的垃圾回收技術(shù),甚至根本就不需要垃圾回收,但是由于內(nèi)存的有限性,JVM在實(shí)現(xiàn)的時(shí)候都有一個(gè)由垃圾回收所治理的堆。垃圾回收是一種動(dòng)態(tài)存儲(chǔ)治理技術(shù),它自動(dòng)地釋放不再被程序引用的對(duì)象,按照特定的垃圾收集算法來實(shí)現(xiàn)資源自動(dòng)回收的功能。
  
  2 垃圾收集的意義
  在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ì)象是"無用信息",這些信息將被丟棄。當(dāng)一個(gè)對(duì)象不再被引用的時(shí)候,內(nèi)存回收它占領(lǐng)的空間,以便空間被后來的新對(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í)間來解決一個(gè)難懂的存儲(chǔ)器問題。在用Java語言編程的時(shí)候,靠垃圾收集機(jī)制可大大縮短時(shí)間。其次是它保護(hù)程序的完整性, 垃圾收集是Java語言安全性策略的一個(gè)重要部份。
  
  垃圾收集的一個(gè)潛在的缺點(diǎn)是它的開銷影響程序性能。Java虛擬機(jī)必須追蹤運(yùn)行程序中有用的對(duì)象, 而且最終釋放沒用的對(duì)象。這一個(gè)過程需要花費(fèi)處理器的時(shí)間。其次垃圾收集算法的不完備性,早先采用的某些垃圾收集算法就不能保證100%收集到所有的廢棄內(nèi)存。當(dāng)然隨著垃圾收集算法的不斷改進(jìn)以及軟硬件運(yùn)行效率的不斷提升,這些問題都可以迎刃而解。
  
  3 垃圾收集的算法分析
  Java語言規(guī)范沒有明確地說明JVM使用哪種垃圾回收算法,但是任何一種垃圾收集算法一般要做2件基本的事情:(1)發(fā)現(xiàn)無用信息對(duì)象;(2)回收被無用對(duì)象占用的內(nèi)存空間,使該空間可被程序再次使用。
  
  大多數(shù)垃圾回收算法使用了根集(root set)這個(gè)概念;所謂根集就量正在執(zhí)行的Java程序可以訪問的引用變量的集合(包括局部變量、參數(shù)、類變量),程序可以使用引用變量訪問對(duì)象的屬性和調(diào)用對(duì)象的方法。垃圾收集首選需要確定從根開始哪些是可達(dá)的和哪些是不可達(dá)的,從根集可達(dá)的對(duì)象都是活動(dòng)對(duì)象,它們不能作為垃圾被回收,這也包括從根集間接可達(dá)的對(duì)象。而根集通過任意路徑不可達(dá)的對(duì)象符合垃圾收集的條件,應(yīng)該被回收。下面介紹幾個(gè)常用的算法。
  
  3.1 引用計(jì)數(shù)法(Reference Counting Collector)
  
  引用計(jì)數(shù)法是唯一沒有使用根集的垃圾回收得法,該算法使用引用計(jì)數(shù)器來區(qū)分存活對(duì)象和不再使用的對(duì)象。一般來說,堆中的每個(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ì)長時(shí)間中斷程序執(zhí)行,適宜地必須 實(shí)時(shí)運(yùn)行的程序。但引用計(jì)數(shù)器增加了程序執(zhí)行的開銷,因?yàn)槊看螌?duì)象賦給新的變量 ,計(jì)數(shù)器加1,而每次現(xiàn)有對(duì)象出了作用域生,計(jì)數(shù)器減1。
  
  3.2 tracing算法(Tracing Collector)
  
  tracing算法是為了解決引用計(jì)數(shù)法的問題而提出,它使用了根集的概念?;趖racing算法的垃圾收集器從根集開始掃描,識(shí)別出哪些對(duì)象可達(dá),哪些對(duì)象不可達(dá),并用某種方式標(biāo)記可達(dá)對(duì)象,例如對(duì)每個(gè)可達(dá)對(duì)象設(shè)置一個(gè)或多個(gè)位。在掃描識(shí)別過程中,基于tracing算法的垃圾收集也稱為標(biāo)記和清除(mark-and-sweep)垃圾收集器.
  
  3.3 compacting算法(Compacting Collector)
  
  為了解決堆碎片問題,基于tracing的垃圾回收吸收了Compacting算法的思想,在清除的過程中,算法將所有的對(duì)象移到堆的一端,堆的另一端就變成了一個(gè)相鄰的空閑內(nèi)存區(qū),收集器會(huì)對(duì)它移動(dòng)的所有對(duì)象的所有引用進(jìn)行更新,使得這些引用 在新的位置能識(shí)別原來 的對(duì)象。在基于Compacting算法的收集器的實(shí)現(xiàn)中,一般增加句柄和句柄表。
  
  3.4 coping算法(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ì)象面,原來的對(duì)象面變成了空閑面,程序會(huì)在新的對(duì)象面中分配內(nèi)存。
  
  一種典型的基于coping算法的垃圾回收是stop-and-copy算法,它將堆分成對(duì)象面和空閑區(qū)域面,在對(duì)象面與空閑區(qū)域面的切換過程中,程序暫停執(zhí)行。
  
  3.5 generation算法(Generational Collector)
  
  stop-and-copy垃圾收集器的一個(gè)缺陷是收集器必須復(fù)制所有的活動(dòng)對(duì)象,這增加了程序等待時(shí)間,這是coping算法低效的原因。在程序設(shè)計(jì)中有這樣的規(guī)律:多數(shù)對(duì)象存在的時(shí)間比較短,少數(shù)的存在時(shí)間比較長。因此,generation算法將堆分成兩個(gè)或多個(gè),每個(gè)子堆作為對(duì)象的一代(generation)。由于多數(shù)對(duì)象存在的時(shí)間比較短,隨著程序丟棄不使用的對(duì)象,垃圾收集器將從最年輕的子堆中收集這些對(duì)象。在分代式的垃圾收集器運(yùn)行后,上次運(yùn)行存活下來的對(duì)象移到下一最高代的子堆中,由于老一代的子堆不會(huì)經(jīng)常被回收,因而節(jié)省了時(shí)間。
  
  3.6 adaptive算法(Adaptive Collector)
  
  在特定的情況下,一些垃圾收集算法會(huì)優(yōu)于其它算法?;贏daptive算法的垃圾收集器就是監(jiān)控當(dāng)前堆的使用情況,并將選擇適當(dāng)算法的垃圾收集器。
  
  4 透視Java垃圾回收
  4.1 命令行參數(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();
   }
  }
  
  在這個(gè)例子中,一個(gè)新的對(duì)象被創(chuàng)建,由于它沒有使用,所以該對(duì)象迅速地變?yōu)榭蛇_(dá),程序編譯后,執(zhí)行命令: java -verbosegc TestGC 后結(jié)果為:
  
  [Full GC 168K->97K(1984K), 0.0253873 secs]
  
  機(jī)器的環(huán)境為,windows 2000 + JDK1.3.1,箭頭前后的數(shù)據(jù)168K和97K分別表示垃圾收集GC前后所有存活對(duì)象使用的內(nèi)存容量,說明有168K-97K=71K的對(duì)象容量被回收,括號(hào)內(nèi)的數(shù)據(jù)1984K為堆內(nèi)存的總?cè)萘?,收集所需要的時(shí)間是0.0253873秒(這個(gè)時(shí)間在每次執(zhí)行的時(shí)候會(huì)有所不同)。
  
  4.2 finalize方法透視垃圾收集器的運(yùn)行
  
  在JVM垃圾收集器收集一個(gè)對(duì)象之前 ,一般要求程序調(diào)用適當(dāng)?shù)姆椒ㄡ尫刨Y源,但在沒有明確釋放資源的情況下,Java提供了缺省機(jī)制來終止化該對(duì)象心釋放資源,這個(gè)方法就是finalize()。它的原型為:
  
  PRotected void finalize() throws Throwable
  
  在finalize()方法返回之后,對(duì)象消失,垃圾收集開始執(zhí)行。原型中的throws Throwable表示它可以拋出任何類型的異常。
  
  之所以要使用finalize(),是由于有時(shí)需要采取與Java的普通方法不同的一種方法,通過分配內(nèi)存來做一些具有C風(fēng)格的事情。這主要可以通過"固有方法"來進(jìn)行,它是從Java里調(diào)用非Java方法的一種方式。C和C++是目前唯一獲得固有方法支持的語言。但由于它們能調(diào)用通過其他語言編寫的子程序,所以能夠有效地調(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)用它。也就是說我們不能過多地使用finalize(),它并不是進(jìn)行普通清除工作的理想場所。
  
  在普通的清除工作中,為清除一個(gè)對(duì)象,那個(gè)對(duì)象的用戶必須在希望進(jìn)行清除的地點(diǎn)調(diào)用一個(gè)清除方法。這與C++"破壞器"的概念稍有抵觸。在C++中,所有對(duì)象都會(huì)破壞(清除)。或者換句話說,所有對(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不答應(yīng)我們創(chuàng)建本地(局部)對(duì)象--無論如何都要使用new。但在Java中,沒有"delete"命令來釋放對(duì)象,因?yàn)槔占鲿?huì)幫助我們自動(dòng)釋放存儲(chǔ)空間。所以假如站在比較簡化的立場,我們可以說正是由于存在垃圾收集機(jī)制,所以Java

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 自拍偷拍999 | 黄色一级片毛片 | 亚洲九草 | 黄色毛片一级 | 国产日本在线播放 | 中文字幕 在线观看 | 最近国产中文字幕 | 亚洲第一成人在线观看 | 色播视频在线播放 | 精品一区二区三区网站 | 久久国产亚洲精品 | 成人在线观看一区 | 91色成人 | av免费大全| 特大黑人videos与另类娇小 | 无码专区aaaaaa免费视频 | 久久久久久久久久久久久久av | 九九热视频这里只有精品 | 91国在线高清视频 | 一区国产在线 | 快播av在线| 草操视频 | 免费看黄色一级片 | 婷婷中文字幕一区二区三区 | 国产一级桃视频播放 | 热re91久久精品国产99热 | 亚洲人成中文字幕在线观看 | 久久精品亚洲欧美日韩精品中文字幕 | 成年人黄色片视频 | 男女做性免费网站 | 亚洲精品aⅴ中文字幕乱码 欧美囗交 | 亚州综合| 久久毛片| 毛片免费看的 | 免费人成在线播放 | 看一级大毛片 | 国产高潮好爽受不了了夜色 | 毛片av网址 | 性少妇freeseⅹbbwhd | 最新中文在线视频 | 国产精品资源手机在线播放 |