![JVM內存結構和垃圾回收](http://p2.ttnews.xyz/loading.gif)
JVM運行時數據區
方法區:永久代 線程共享 用於存儲已被虛擬機加載的類信息、常量、靜態變量、JIT編譯後的代碼等數據。
堆(Heap):新生代,老年代 線程共享 所有的對象實例以及都要在堆上分配。
虛擬機棧:VM Stack 線程私有 Java方法執行的內存模型:方法執行時創建棧幀(Stack Frame)用戶存儲局部變量表、操作數棧、動態鏈接、方法入口等信息。每個方法從調用直至執行完成的過程就對應著一個棧幀在VMStack 中的入棧和出棧過程
本地方法棧:Native Method Stack 與VM Stack 類似,區別在於VM Stack為虛擬機執行Java方法(字節碼)服務,而Native Method Stack則是VM使用到的Native方法服務
程序計數器:Program CounterRegister 線程私有 可看作是當前線程所執行的字節碼行號指示器
所有的對象實例以及都要在堆上分配。
The heap is the runtime data area from which memory for all class instances and arrays is allocated.
垃圾回收
垃圾回收主要發生在堆中。
引用計數:難以解決對象之間的相互循環引用的問題,一般JVM不用,但是Pythoon中會用到
可達性分析算法
JVM一般使用可達性分析算法帶判斷垃圾
使用GC Roots作為起始點,向下搜索,當發現與GC Roots沒有關聯則判定為可以回收的對象
可作為GC Roots的對象
1. VM Stack(棧幀中的本地變量表)中引用的對象
2. 方法區中類靜態屬性引用的對象
3. 方法區中常量引用的對象
4. 本地方法棧中JNI引用的對象
垃圾收集算法
1.標記清除(Mark-Sweep):最基礎的算法,兩點不足:1.效率問題,標記和清除效率都不高 2.空間問題,會產生大量不連續的內存碎片
2.複製算法
把heap分為兩塊,有用的複製到另一個塊,清除原來的塊
現代商業JVM都採用這種算法來回收新生代:
將內存劃分為較大的Eden和Survivor,HotSpot默認是8:1
3.標記整理
4.分代收集
內存分配與回收策略
1. 對象優先在Eden分配
2. 大對象直接進入老年代(很長的字符串和數組,寫代碼應當避免短命大對象)
3. 長期存活的對象直接進入老年代
4. 動態對象年齡判斷(在Survivor空間中,如果相同年齡所以對象大小的總和大於Survivor空間的一半,年齡大於等於該年齡的對象直接進入老年代)
5. 空間分配擔保
閱讀更多 Java技術進階 的文章