垃圾收集機制的基本原理及方法

          2.1 JVM中內存的劃分

            垃圾收集器對Java程序員來說,基本上是透明的,但是只有了解GC的工作原理、如何優化GC的性能、如何與GC進行有限的交互,才能提高整個應用程序的性能、全面提升內存的管理效率,為了說明其工作方式,我們首先看看內存中幾種常用的存放數據的地方:

            (1) 堆棧(Stack):位于常規RAM(隨機訪問存儲器)區域,但可通過它的“堆棧指針”獲得處理器的直接支持。堆棧指針若向下移,會創建新的內存;若向上移,則會釋放那些內存。這是一種特別快、特別有效的數據保存方式,僅次于CPU的寄存器。創建程序時,Java編譯器必須準確地知道堆棧內保存的所有數據的“長度”以及“存在時間”。這是由于它必須生成相應的代碼,以便向上和向下移動指針。這一限制無疑影響了程序的靈活性,所以盡管有些Java數據要保存在堆棧里--特別是對象的引用(也可稱為對象的引用變量),但Java中的對象不會放在其中。

            (2) 堆(Heap)。一種常規用途的內存池(也在RAM區域),其中保存了Java對象。和堆棧不同,“內存堆”或“堆”(Heap)最吸引人的地方在于編譯器不必知道要從堆里分配多少存儲空間,也不必知道存儲的數據要在堆里停留多長的時間。因此,用堆保存數據時會得到更大的靈活性。要求創建一個對象時,只需用new命令編制相關的代碼即可。執行這些代碼時,會在堆里自動進行數據的保存。當然,為達到這種靈活性,必然會付出一定的代價:在堆里分配存儲空間時會花掉更長的時間!這是導致Java性能不佳的因素之一。

            SUN的JVM使用分代方式(Generation)管理堆空間,“代”分配給新舊對象的內存池。這些對象的不斷積累會導致一個的內存狀態,從而推動垃圾收集的開始。如圖說明了SUN的JVM中堆空間粗略的劃分。

            年輕的一代包括年輕的對象空間(eden)和兩個存活(survivor)空間(SS#1和SS#2)。新對象被分配到eden中,那些存活較久的對象則會從年輕的一代轉移到老一代中。圖中的Perm段叫做永久代(permanent generation),它保存了JVM的類和方法對象。

            (3) 靜態存儲(Static)。這兒的“靜態”(Static)是指“位于固定位置”(盡管也在RAM里)或是有且僅有一份。程序運行期間,靜態存儲的數據將隨時等候調用。可用static關鍵字指出一個對象的特定元素是靜態的。但Java對象本身永遠都不會置入靜態存儲空間。

             2.2 對象在內存中的分配?

            了解了內存中這些存放數據的方式后,我們先來看看C++中存放對象的機制:在C++中,對象可以是在堆棧中創建的,這樣可達到更快的速度。然而,在C++里創建“內存堆”(Heap)對象通常會慢得多。這種內存堆實際是一個大的內存池,要求必須進行再循環(再生)。這里可以把C++的Heap想象是一塊場地,在這里面中每個對象不斷監視屬于自己的地盤,他們可能在以后的某個時刻不再繼續占用目前所占用的空間,即釋放后的內存會在堆里留下一個洞,所以再調用new的時候,存儲分配機制必須進行某種形式的搜索,使新對象能夠利用已經存在的空洞,否則就會很快用光堆的存儲空間。之所以內存堆的分配會在C++里對性能造成如此重大的性能影響,對可用內存的搜索正是一個重要的原因。所以創建基于堆棧的對象要快得多。

            而在Java中的內存堆(Heap)更像一條傳送帶:每次分配了一個新對象后,“Heap指針”都會朝前移動,這意味著對象存儲空間的分配可以達到非常快的速度。因為“Heap指針”只是單純的往前移動至未經分配的區域,所以它與C++的堆棧分配方式幾乎是不相上下的(當然,在數據記錄上會多花一些開銷,但要比搜索存儲空間快多了)。但是如果只是按那種方式分配,最終就要求進行大量的內存頁面交換(這對性能的發揮會產生巨大干擾),而且終究會用光內存,出現內存分頁錯誤(page fault)。所以Java引入了“垃圾收集器”。它在收集“垃圾”的同時,也負責重新緊密排列(compact)堆里的所有對象,消除內存空洞,將“堆指針”移至盡可能靠近傳送帶開頭的地方,遠離發生(內存)分頁錯誤的地點。垃圾收集器會重新安排所有東西,使其成為一個高速、無限自由的堆模型,同時游刃有余地分配存儲空間。但是垃圾收集時的代價是非常高昂的,這也是導致Java性能不佳的因素之一。

          posted on 2006-12-15 17:48 小橋 流水 閱讀(462) 評論(0)  編輯  收藏 所屬分類: java技術

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 和顺县| 开封市| 轮台县| 呼图壁县| 会昌县| 临沧市| 邯郸市| 抚顺市| 三河市| 怀安县| 玉龙| 合江县| 湘潭县| 新干县| 鄂托克前旗| 临猗县| 蓬安县| 石家庄市| 达孜县| 抚顺市| 安仁县| 裕民县| 新乡县| 天等县| 准格尔旗| 石台县| 米脂县| 台东市| 柳林县| 呼玛县| 封开县| 建水县| 敦化市| 嘉祥县| 株洲市| 滁州市| 宁津县| 通化市| 定州市| 湟源县| 汉源县|