標籤:jvm java
一、記憶體回收作用於“堆”和“非堆(方法區)”兩個線程共用的部分。
1、堆:
堆的主要存放“產生的對象”和“開闢的數組”。
面試的時候可能會問道,是不是所有的對象都存在於堆上?答案是否定的,當前虛擬機器最佳化技術的發展,其中出現了逃逸分析(如果一個方法中產生的對象沒有被其他方法或者線程使用,那麼就是不逃逸的),如果對象不逃逸,那麼就會把對象分配到棧空間上。另,網上有人還列舉了TLAB,但是TLAB是存在於Eden之上的。
如,我們來分析下對的組成,堆分為“Young(新生的)”和“Old(老年代)”兩部分,其中Young中又分為一個“Eden”和兩個“Survivor”。
1)大部分“對象”會分配到Eden中,如果Eden空間不夠用了,將會發起Minor GC,會將Eden中存活的對象和其中一個Survivor中存活並且沒有晉陞到Old的對象,複製到另一個Survivor中。
如果Survivor中的空間不夠用,將會將剩餘的對象複製到Old地區中。(其中的限制,看4))
註:任何時候,兩個Survivor都只有一個被利用,且預設的時候Eden:Survivor=8:1。
2)大對象(需要很長的連續空間,如很長的字串、數組)直接分配到Old地區。
3)在1)中,Minor GC之後,原先在Survivor的對象如果依舊在其中,那麼他的”年齡“將會+1,如果年齡值>15(由-XX:MaxTenuringThreshold設定),將會晉陞至Old地區。
或者,在Survivor中相同年齡的對象佔了其空間了一半以上,此時年齡大於前者的都會直接晉級到Old地區。
4)以上晉陞或者拷貝到Old地區的前提是,Old有足夠的連續空間能容納Young中所有對象的大小的情況;如果不夠,將會在Old中進行Full GC。
2、非堆(方法區)
方法區回收的主要動作是“常量池”清理和“類型卸載”
1)常量池
包括:常量,【類(介面)、方法、字元】的符號引用
上述中,如果沒有被引用,將可以被回收。
2)類型卸載
(1)不再存在執行個體
(2)相應的ClassLoader被卸載
(3)java.lang.Class對象不再引用,也即不再有反射操作。
之後,就“可以”被回收。
二、附帶複習下虛擬機器運行時資料
1、程式計數器
2、Java虛擬機器棧(線程私人,方法堆出即銷毀)
每個方法有會建立一個真棧,其中包括“局部變數表”,“運算元棧”,“動態連結”,“方法出口”等。
其中局部變數表包括:
1)基礎資料型別 (Elementary Data Type),int long等
2)對象的引用
3)returnAddress類型
3、本地方法棧(線程私人)被Native方法使用
4、堆(會被記憶體回收)
5、非堆(會被記憶體回收)
林子木
部落格地址:http://blog.csdn.net/wolinxuebin/
參考資料:《深入理解Java虛擬機器》 周志明
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Java JVM 記憶體回收