介紹一些JVM內(nèi)存區(qū)

Person person=new Person("張三"); 在這個語句中 哪部分是對象,哪部分是對象的引用 然后它們分別存儲在JVM的哪個區(qū)域內(nèi)?
Person是類 類是抽象的 new出來之后才真正存在。所以對象另一種說法是實例,是這個類的實例。
person是Person類對象的引用
new Person("張三")是創(chuàng)建一個對象
person存儲在JAVA棧中 對象存儲在堆中。
一個引用可以指向多個對象,一個對象也可以指向多個引用。
如何判斷一個對象會被垃圾回收
有兩種方法,一種是引用計數(shù)法,一種是可達性分析法(JAVA中采用這種)。引用計數(shù)法就是計算一個對象是否有被引用,如果當沒有沒任何變量引用的話就可以回收了。
達性分析法:該方法的基本思想是通過一系列的“GC Roots”對象作為起點進行搜索,如果在“GC Roots”和一個對象之間沒有可達路徑,則稱該對象是不可達的,不過要注意的是被判定為不可達的對象不一定就會成為可回收對象。被判定為不可達的對象要成為可回收對象必須至少經(jīng)歷兩次標記過程,如果在這兩次標記過程中仍然沒有逃脫成為可回收對象的可能性,則基本上就真的成為可回收對象了。
舉幾個對象會被垃圾回收的例子
顯示地將某個引用賦值為null或者將已經(jīng)指向某個對象的引用指向新的對象
Object obj = new Object();
obj = null;
Object obj1 = new Object();
Object obj2 = new Object();
obj1 = obj2;
obj因為指向null,所以會導致之前new的對象回收,obj1因為指向了obj2,導致沒有引用指向之前new的對象。也會被回收。
局部引用所指向的對象,比如下面這段代碼:
void fun() {
for(int i=0;i<10;i++) {
Object obj = new Object();
System.out.println(obj.getClass());
}
}
只有弱引用與其關聯(lián)的對象,比如:
WeakReference<String> wr = new WeakReference<String>(new String("world"));
有哪些典型的垃圾回收算法以及使用場景?
Mark-Sweep(標記-清除)算法、Copying(復制)算法、Mark-Compact(標記-整理)算法
介紹一下 Mark-Sweep(標記-清除)算法、Copying(復制)算法、Mark-Compact(標記-整理)算法的過程
Mark-Sweep(標記-清除)算法
標記-清除算法分為兩個階段:標記階段和清除階段。標記階段的任務是標記出所有需要被回收的對象,清除階段就是回收被標記的對象所占用的空間。

從圖中可以很容易看出標記-清除算法實現(xiàn)起來比較容易,但是有一個比較嚴重的問題就是容易產(chǎn)生內(nèi)存碎片,碎片太多可能會導致后續(xù)過程中需要為大對象分配空間時無法找到足夠的空間而提前觸發(fā)新的一次垃圾收集動作。
Copying(復制)算法
為了解決產(chǎn)生內(nèi)存碎片的問題,復制算法的特點是,每次將內(nèi)存區(qū)分成兩塊相等的部分,然后使用其中一塊,當這塊內(nèi)存用完之后,將存活的對象復制到另一塊,然后對已使用的那塊一次清理掉。這樣就保證了碎片不會過多。

這種算法雖然實現(xiàn)簡單,運行高效且不容易產(chǎn)生內(nèi)存碎片,但是卻對內(nèi)存空間的使用做出了高昂的代價,因為能夠使用的內(nèi)存縮減到原來的一半。
很顯然,Copying算法的效率跟存活對象的數(shù)目多少有很大的關系,如果存活對象很多,那么Copying算法的效率將會大大降低。
Mark-Compact(標記-整理)算法
第一步標記和第一個介紹的標記清楚一樣,對使用了的內(nèi)存塊進行標記。然后把存活對象都向一端移動填按順序充滿內(nèi)存塊,然后清理掉端邊界以外的內(nèi)存。

Generational Collection(分代收集)算法
一般情況下將堆區(qū)劃分為老年代(Tenured Generation)和新生代(Young Generation),老年代的特點是每次垃圾收集時只有少量對象需要被回收,而新生代的特點是每次垃圾回收時都有大量的對象需要被回收,那么就可以根據(jù)不同代的特點采取最適合的收集算法。
新生代采用復制算法,老年代采用標記整理算法
一般來說是將新生代劃分為一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden空間和其中的一塊Survivor空間,當進行回收時,將Eden和Survivor中還存活的對象復制到另一塊Survivor空間中,然后清理掉Eden和剛才使用過的Survivor空間。
注意,在堆區(qū)之外還有一個代就是永久代(Permanet Generation),它用來存儲class類、常量、方法描述等。對永久代的回收主要回收兩部分內(nèi)容:廢棄常量和無用的類。
Full GC Major GC Minor GC 區(qū)別
Major GC通常是跟full GC是等價的,收集整個GC堆。也有說
Major GC是清除 老年代的
Minor GC是清除 新生代的
Full GC是清除老年代和新生代的
Minor GC的觸發(fā)條件:當新生代中的eden區(qū)分配滿的時候觸發(fā)
Full GC觸發(fā)條件:
(1)調(diào)用System.gc時,系統(tǒng)建議執(zhí)行Full GC,但是不必然執(zhí)行
(2)老年代空間不足
(3)方法區(qū)空間不足
(4)通過Minor GC后進入老年代的平均大小大于老年代的可用內(nèi)存
(5)由Eden區(qū)、From Space區(qū)向To Space區(qū)復制時,對象大小大于To Space可用內(nèi)存,則把該對象轉(zhuǎn)存到老年代,且老年代的可用內(nèi)存小于該對象大小
有哪些典型的垃圾收集器 以及它們使用的垃圾回收算法
1.Serial/Serial Old
Serial/Serial Old收集器是最基本最古老的收集器,它是一個單線程收集器
2.ParNew
ParNew收集器是Serial收集器的多線程版本,使用多個線程進行垃圾收集。
3.Parallel Scavenge
Parallel Scavenge收集器是一個新生代的多線程收集器(并行收集器)
4.CMS
CMS(Current Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器,它是一種并發(fā)收集器,采用的是Mark-Sweep算法
對象內(nèi)存分配規(guī)則
對象主要分配在新生代的Eden Space和From Space,然后如果這兩塊地區(qū)的內(nèi)存不足,那么就會發(fā)生一次Minor GC ,把這兩塊的內(nèi)存中的對象復制到To Space,然后將Eden Space和From Space進行清理。如果在清理的過程中,To Space無法足夠來存儲某個對象,就會將該對象移動到老年代中
在進行了GC之后,使用的便是Eden space和To Space了,下次GC時會將存活對象復制到From Space,如此反復循環(huán)。當對象在Survivor區(qū)躲過一次GC的話,其對象年齡便會加1,默認情況下,如果對象年齡達到15歲,就會移動到老年代中。
一般來說,大對象會被直接分配到老年代,所謂的大對象是指需要大量連續(xù)存儲空間的對象,最常見的一種大對象就是大數(shù)組,比如:
byte[] data = new byte[4 * 1024 * 1024]
