Android內存泄漏相關

woobhurk 9年前發布 | 14K 次閱讀 JVM 虛擬化 Android開發 移動開發

來自: http://blog.csdn.net/u011669081/article/details/50575430

Android開發過程中,因為開發的不規范,數據處理的不當方式,常常會造成內存泄漏。內存泄漏,可以用一句話來概括,該釋放的對象未釋放。

在Java方面探討:Java語言是有垃圾回收機制的,理論上是沒有泄漏的,但事實上有些情況下,Java的垃圾回收機制是無法做到垃圾回收的,例如:我們使用完一個對象后,并且不再使用,但是仍然保留著對這對象的引用,那么垃圾回收器就無法去回收這對象,造成不必要的內存泄漏。相比于C語言不同,C語言本身沒有垃圾回收機制,需要程序員自己去編寫操作內存。先來了解下Java GC(Garbage Collection)垃圾回收機制,簡單的來說,垃圾回收機制對JVM(Java Virtual Machine)中的內存做處理,判斷哪些內存需要被回收,然后根據一定策略去釋放被占有的內存,保證JVM內存的足夠空間。

垃圾回收機制會做三件事:

- 判斷哪些內存需要回收 - 什么時候開始回收 - 怎么去回收內存

理解垃圾回收機制需要知道的幾點:

- 內存是怎么分配的?

堆區:在垃圾回收機制中,堆區是垃圾垃圾回收機制中最大的管理內存的區域,堆區由所有線程共享。堆區的存在是為了存儲對象實例,理論上說,所有的對象都在堆區上分配內存。

方法區(Method Area)(引用下別人的總結):在Java虛擬機規范中,將方法區作為堆的一個邏輯部分來對待,但事實 上,方法區并不是堆(Non-Heap);另外,不少人的博客中,將Java GC的分代收集機制分為3個代:青年代,老年代,永久代,這些作者將方法區定義為“永久代”,這是因為,對于之前的HotSpot Java虛擬機的實現方式中,將分代收集的思想擴展到了方法區,并將方法區設計成了永久代。不過,除HotSpot之外的多數虛擬機,并不將方法區當做永 久代,HotSpot本身,也計劃取消永久代。本文中,由于筆者主要使用Oracle JDK6.0,因此仍將使用永久代一詞。方法區是各個線程共享的區域,用于存儲已經被虛擬機加載的類信息(即加載類時需要加載的信息,包括版本、field、方法、接口等信息)、final常量、靜態變量、編譯器即時編譯的代碼等。方法區在物理上也不需要是連續的,可以選擇固定大小或可擴展大小,并且方法區比堆還多了一個限制:可以選擇是否執行垃圾收集。一般的,方法區上 執行的垃圾收集是很少的,這也是方法區被稱為永久代的原因之一(HotSpot),但這也不代表著在方法區上完全沒有垃圾收集,其上的垃圾收集主要是針對 常量池的內存回收和對已加載類的卸載。

程序計數器:程序計數器是個非常小的內存區域,通常只用來標記程序運行到哪行代碼,字節碼解釋器在工作時,會通過改變這個計數器的值來取下一條語句指令。

虛擬機棧:線程內的每個方法在運行的同時,都會創建一個棧幀。棧幀中存儲的有:

1. 局部變量表

2. 操作站

3. 動態鏈接

4. 方法出口

方法被調用時,棧幀在JVM棧中入棧,當方法執行完成時,棧幀出棧。

局部變量表中存儲著方法的相關局部變量,包括數據類型,對象引用,返回地址。

虛擬機棧中定義了兩中異常:

1.棧溢出:線程調用的棧深度大于虛擬機允許的棧深度。

2.內存溢出:多數JVM都允許動態擴展虛擬機棧的大小(有少部分是固定長度的),所以線程可以一直申請棧,直到內存不足。

本地方法棧:類似于虛擬機棧,唯一的區別是:虛擬機棧是執行Java方法的,而本地方法棧是用來運行native方法的。

Java內存分配機制

Java內存分配機制:分代分配,然后分代回收。

對象根據對象的存活時間被分為:年輕代,年老代,永久代。

1.年輕代:對象被創建時,內存的分配通常發生在年輕代,大多數對象在創建后很快就基本不再使用了,于是被年輕代的垃圾回收機制回收了。關于年輕代:分為三個區域,一個Eden區,兩個存活區。同時年輕代方面遵守以下幾條:1.絕大多數會創建在Eden區,其中大多數對象會很快消亡,Eden區是連續的內存空間,所以在分配內存上速度極快。2.當Eden區存滿時,將消亡的對象清理掉,并將剩余的對象復制到一個存活區0。3當存活區0也滿時,將存活的對象直接復制到存活區1。總的來說:Eden區是連續空間,而存活區總有一個保持為空。

 本文由用戶 woobhurk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!