從抽象的JVM的角度去看分爲:堆(Heap),棧(Stacks),方法區(MethodArea),運行時常量池(RuntimeConstant Pool),本地方法棧(NativeMethod Stacks),PC Register(PC寄存器)。java
區別:堆是不連續的內存區域,堆空間比較靈活也特別大。 棧式一塊連續的內存區域,大小是有操做系統覺決定的。堆管理很麻煩,頻繁地new/remove會形成大量的內存碎片,這樣就會慢慢致使效率低下。對於棧的話,他先進後出,進出徹底不會產生碎片,運行效率高且穩定。算法
咱們一般說的內存泄露,GC,是針對Heap內存的. 由於Stack內存在函數出棧的時候就銷燬了。函數
public class A{ int a = 1; Student s1 = new Student();
public void Test(){ int b = 1; Student s2 = new Student(); } }
請問a的內存在哪裏,b的內存在哪裏,s1,s2的內存在哪裏?記住下面兩句話。大數據
因此答案就是a,s1, s2對象都在堆中,b和s2對象引用在棧中。spa
從JDK1.2版本開始,把對象的引用分爲四種級別,從而使程序能更加靈活的控制對象的生命週期。這四種級別由高到低依次爲:強引用、軟引用、弱引用和虛引用。操作系統
當一個對象已經不須要再使用了,本該被回收時,而有另一個正在使用的對象持有它的引用,從而就致使對象不能被回收。這種致使了本該被回收的對象不能被回收而停留在堆內存中,就產生了內存泄漏。線程
內存泄露的場景有不少。code
非靜態內部類的靜態實例
因爲內部類默認持有外部類的引用,而靜態實例屬於類。因此,當外部類被銷燬時,內部類仍然持有外部類的引用,導致外部類沒法被GC回收。所以形成內存泄露。對象
類的靜態變量持有大數據對象
靜態變量長期維持到大數據對象的引用,阻止垃圾回收。blog
資源對象未關閉
資源性對象如Cursor、Stream、Socket,Bitmap,應該在使用後及時關閉。未在finally中關閉,會致使異常狀況下資源對象未被釋放的隱患。
註冊對象未反註冊
咱們經常寫不少的Listener,未反註冊會致使觀察者列表裏維持着對象的引用,阻止垃圾回收。
Handler經過發送Message與主線程交互,Message發出以後是存儲在MessageQueue中的,有些Message也不是立刻就被處理的。
這個太多了,不細說,單利模式寫的不恰當就屬於這種。
根搜索算法是從離散數學中的圖論引入的,程序把全部的引用關係看做一張圖,從一個節點GC ROOT開始,尋找對應的引用節點,找到這個節點之後,繼續尋找這個節點的引用節點,當全部的引用節點尋找完畢以後,剩餘的節點則被認爲是沒有被引用到的節點,即無用的節點。若是這個對象是引用可達的, 則稱之爲活的(live), 反之, 若是這個對象引用不可達, 則稱之爲死的(dead), 也能夠稱之爲垃圾(garbage).這個引用可達與不可達就是相對於GC Root來講的,在上圖中,左邊4個對象就是活的,右邊兩個就是死的,也就是咱們說的能夠被回收的垃圾。