一、內(nèi)存簡介
根據(jù)《Java虛擬機規(guī)范(第2版)》的規(guī)定,Java虛擬機所管理的內(nèi)存將會包括以下幾個運行時數(shù)據(jù)區(qū)域,如下圖所示:
經(jīng)常人把Java內(nèi)存區(qū)分為堆內(nèi)存(Heap)和棧內(nèi)存(Stack),這種分法比較粗糙,Java內(nèi)存區(qū)域的劃分實際上遠比這復(fù)雜。這種劃分方式的流行是因為大多數(shù)程序員最關(guān)注的、與對象內(nèi)存分配關(guān)系最密切的內(nèi)存區(qū)域是這兩塊。
通常所說的堆(Heap),此內(nèi)存區(qū)域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內(nèi)存。這一點在Java虛擬機規(guī)范中的描述是:所有的對象實例以及數(shù)組都要在堆上分配。
通常所說的棧(Stack),是指虛擬機棧。虛擬機棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法被執(zhí)行的時候都會同時創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表、操作棧、動態(tài)鏈接、方法出口等信息。
每一個方法被調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀在虛擬機棧中從入棧到出棧的過程。局部變量表存放了編譯期可知長度的各種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference類型,它不等同于對象本身,是對象在堆內(nèi)存的首地址)。
因此局部變量表所需的內(nèi)存空間在編譯期間完成分配,當(dāng)進入一個方法時,這個方法需要在幀中分配多大的局部變量空間是完全確定的,在方法運行期間不會改變局部變量表的大小。 方法執(zhí)行完,自動釋放。
方法區(qū)(Method Area)用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)。
二、垃圾回收機制
垃圾回收(Garbage Collection,GC):在程序的運行環(huán)境中,JVM(Java虛擬機)提供了一個系統(tǒng)級的垃圾回收器線程,它負責(zé)自動回收那些無用對象所占用的堆內(nèi)存。這種內(nèi)存回收的過程被稱為垃圾回收。
Java語言中,內(nèi)存回收任務(wù)由JVM來擔(dān)當(dāng)。
Java的垃圾回收機制是JVM提供的能力,由單獨的系統(tǒng)級垃圾回收線程在空閑時間以不定時的方式動態(tài)回收無任何引用的對象占據(jù)的堆內(nèi)存空間。
(1)程序只能決定一個對象不再被任何引用變量引用,使得它成為可以被回收的垃圾。
類比:決定什么樣的東西扔掉
(2)不能決定垃圾回收的時間。垃圾回收器作為低優(yōu)先級線程獨立運行。在任何時候,程序都無法迫使垃圾回收器立即執(zhí)行垃圾會后操作。
類比:居民把無用物品放在指定的地方,清潔工人會把它收拾走。但垃圾被收走的時間,居民是不知道的,也無需了解。
(3)程序中可調(diào)用System.gc()或Runtime.gc()方法提示垃圾回收器盡快執(zhí)行垃圾回收操作,但是不能保證調(diào)用后垃圾回收器會立即執(zhí)行垃圾回收。
類比:小區(qū)垃圾成堆時,居民打電話給環(huán)保局,催促清潔工盡快來處理垃圾。但是清潔工不一定立即就來了,也有可能很長時間后再來。
Slogan:程序員的聚集地,和一幫喜歡學(xué)習(xí)的朋友共同成長。