工具選擇
- Memory Profiler
- Memory Analyzer(MAT)
- LeakCanary
Java內存管理機制
標記-清除算法(Mark-Sweep GC)
標記可回收的內存塊,直接對其進行回收。
優點:效率快
缺點:內存空洞比較多
複製算法(Copying GC)
把所有內存一份爲二,可使用內存佔其中一半,進行回收時,把可用內存塊搬移到另一半內存中。
優點:解決了內存空洞
缺點:無法充分使用內存,永遠只能使用一半內存
標記-整理算法 或 標記-壓縮算法(Mark-Compact GC)
結合了標記-清理算法和複製算法的思想。
標記過程與“標記-清理算法”一樣
標記的內存塊進行回收後,存活內存塊進行整理
最後清理內存
分代收集算法
結合了上述的多種收集算法
把內存塊進行了分類,分“新生代”和“老年代”
存活週期短的內存塊,劃分爲“新生代”,直接使用“複製算法”進行回收
存活週期長的內存塊,劃分爲“老年代”,使用“標記-整理算法”
針對分代收集的具體資料:
Java虛擬機:垃圾收集算法 - 方誌朋的博客
Java Garbage Collection Basics
《深入理解java虛擬機》筆記2——GC算法與內存分配策略 | Joker’s Blog | 個人分享博客
Android中的內存管理機制
內存彈性分配,分配值與最大值受具體設備影響。
app打開時內存分配不是固定額度,而是根據app需要的內存進行分配,可大可小。然而這個分配值也依據不同設備受到影響。比如2G內存的手機和4G內存手機,它們的分配值和最大值就不相同。
OOM場景:內存真正不足和可用內存不足
outOfMemory異常需要區分場景。
- 內存真正不足:假設當前設備可給app分配的最大內存是256m,而此時app已經使用了250m,當app在申請需要10m內存時,超過了可分配的內存,則報oom錯誤
- 可用內存不足:假設當前設備的內存已經完全用完,再沒有更多空間可以分配,而我們的app又去申請內存,也會報oom錯誤。這種情況,完全是內存耗盡,受運行整體環境而定。
這兩個場景需要區分一下。
Dalvik和Art區別
Dalvik使用什麼算法,是在編譯期決定的。
如果編譯指令指定“WITH_COPYING_GC”,則使用“複製算法”,否則使用“標記-清理算法”。所以,Dalvik始終只有一個回收算法。Art使用什麼算法,可以在運行時決定。
即,當app運行在前臺時,這時響應性是很重要的,所以使用效率高的“標記-清除算法”(Foreground GC)。
當app運行在了後臺,響應性就不是那麼重要了,可以慢慢清理,同時整理一下內存塊,就可以使用“標記-整理算法”(Background GC)
針對Dalvik和Art的GC具體資料:
Android GC原理探究 - 知乎
Low Memory Killer
- 進程分類:前臺進程,可見進程,服務進程,後臺進程,空進程
- 前臺進程
與用戶正在交互的Activity或者Activity用到的Service等,如果系統內存不足時前臺進程是最後被殺死的。 - 可見進程
處於暫停狀態(onPause)的Activity或者綁定在其上的Service,即被用戶 可見,但由於失去了焦點而不能與用戶交互。例如:Activity彈出一個dialog,當前的Activity就是可見進程 - 服務進程
其中運行着使用startService方法啓動的Service,雖然不被用戶可見,但是卻是用戶關心的,例如用戶正在非音樂界面聽的音樂或者正在非下載頁面自己下載的文件等;當系統需要空間運行前兩者進程(–>指的是前臺進程和可見進程)時纔會被終止. - 後臺進程
運行着執行onStop方法而停止的程序,但是卻不是用戶當前關心的,例如後臺掛着的QQ,這樣的進程系統一旦沒了有內存就首先被殺死. - 空進程
不包含任何應用程序的程序組件的進程,這樣的進程系統是一般不會讓他存在的,爲了進行緩存,使下次App啓動的時候更快,當系統需要內存是最先被殺死。
- 前臺進程
系統會根據進程等級,優先回收低等級進程。
- 回收收益
視情況回收內存,可大可小。