調皮的內存抖動?前生今世及App解決卡頓慢

內存抖動

·內存抖動是指內存頻繁地分配和回收,而頻繁的gc會致使卡頓,嚴重時和內存泄漏同樣會致使OOM。android

注意內存抖動爲何會形成OOM這關係到Java的垃圾回收。算法

形成的緣由

主要是頻繁(很重要)在循環裏建立對象數組

  • 一、致使大量對象在短期內被建立,因爲新對象是要佔用內存空間的並且是頻繁,若是一次或者兩次在循環裏建立對象對內存影響不大,不會形成嚴重內存抖動這樣能夠接受也不可避免緩存

  • 二、頻繁的話就很內存抖動很嚴重性能優化

簡單的提一下垃圾回收機制

垃圾回收微信

在對對象進行回收前須要對垃圾進行採集,不一樣的虛擬機實現可能使用不一樣的垃圾收集算法,不一樣的收集算法的實現也不盡相同。不一樣的算法各有各的優劣勢。app

經常使用的收集算法有:

一、標記-清除算法 Mark-Sweepjvm

和他的名字同樣,算法分爲標記和清除兩個階段:首先標記出全部須要回收的對象,在標記完成後統一回收被標記的對象。函數

二、複製算法 Copying工具

「複製」(Copying)的收集算法,它將可用內存按容量劃分爲大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活着的對象複製到另一塊上面,而後再把已使用過的內存空間一次清理掉。

三、標記壓縮算法 Mark-Compact

內存抖動爲何會形成 OOM?

首先咱們要了解一些垃圾回收機制的來龍去脈

在對對象進行回收前須要對垃圾進行採集,不一樣的虛擬機實現可能使用不一樣的垃圾收集算法,不一樣的收集算法的實現也不盡相同。不一樣的算法各有各的優劣勢。

經常使用的收集算法有:

一、標記-清除算法 Mark-Sweep 二、複製算法 Copying 三、標記壓縮算法 Mark-Compact

不管是通常的JVM仍是DVM,不會只使用一種垃圾收集算法。它會根據內存的劃分實現不一樣的收集算法。

當前商業虛擬機的垃圾收集都採用分代收集算法。分代的垃圾回收策略,是基於不一樣的對象的生命週期是不同的。所以,不一樣生命週期的對象能夠採起不一樣的收集方式,以便提升回收效率。

在Java程序運行的過程當中,會產生大量的對象,因每一個對象所能承擔的職責不一樣所具備的功能不一樣因此也有着不同的生命週期,有的對象生命週期較長,好比Android中的Application、啓動的Service等;有的對象生命週期較短,好比一些函數內部new出來的String對象。

在不進行對象存活時間區分的狀況下,每次垃圾回收都是對整個堆空間進行回收,那麼消耗的時間相對會很長,並且對於存活時間較長的對象進行的掃描工做等都是徒勞。所以就須要引入分治的思想,所謂分治的思想就是因地制宜,將對象進行代的劃分,把不一樣生命週期的對象放在不一樣的代上使用不一樣的垃圾回收方式。

如今主流的作法是將Java堆被分爲

  • 一、新生代
  • 二、老年代;

新生代又被進一步劃分爲Eden和Survivor區, Survivor由From Space和To Space組成

這樣劃分的好處是爲了更快的回收內存,根據不一樣的分代執行不一樣的回收算法;

Android 虛擬機的由來

Java 虛擬機是一個規範,任何實現該規範的虛擬機均可以用來執行 Java 代碼。android就是以爲如今使用的jvm用着不爽,因爲 Androd 運行在移動設備上,內存以及電量等諸多方面跟通常的 PC 設備都有本質的區別 ,通常的 JVM 無法知足移動設備的要求,因此本身根據這個規範開發了一個Dalvik 虛擬機。

Dalvik虛擬機主要使用標記清除算法,也能夠選擇使用拷貝算法。這取決於編譯時期:

ART 是在 Android 4.4 中引入的一個開發者選項,也是 Android 5.0 及更高版本的默認 Android 運行時。google已再也不繼續維護和提供 Dalvik 運行時,如今 ART 採用了其字節碼格式。

ART 有多個不一樣的 GC 方案,這些方案包括運行不一樣垃圾回收器。默認方案是 CMS。
複製代碼

這就是內存抖動爲何會形成 Android App OOM。

檢測優化內存抖動

內存抖動在Android Profile中表現爲:

內存抖動在Android Profile中表現

關於內存抖動和內存泄漏就到這裏了,接下來就說一下Android studio 提供的內存優化方面的工具

**一、利用Alloctions Tracker來進行排查。**前提AndroidStudio版本>=3.0, 在Android Studio中點擊memory profiler中的紅點錄製一段時間的內存申請狀況,再點擊結束。 Android Studio提供了工具來幫助開發者發現和解決內存抖動和內存泄漏。

二、 Tool - Memory Monitor(用於發現內存抖動及內存泄漏的)

Android Studio中的Memory Monitor能夠很好的幫組咱們查看程序的內存使用狀況。 Memory Monitor:查看整個app所佔用的內存,以及發生GC的時刻,短期內發生大量的GC操做是一個危險的信號(用於發現有沒有內存泄漏和嚴重內存抖動)。

(後面兩個是用於定位的內存抖動和內存泄漏發生的具體位置·) Allocation Tracker:使用此工具來追蹤內存的分配,前面有提到過。

Heap Tool:查看當前內存快照,便於對比分析哪些對象有多是泄漏了的.

舉個栗子

你須要避免在for循環裏面分配對象佔用內存,須要嘗試把對象的建立移到循環體以外,自定義View中的onDraw方法也須要引發注意,每次屏幕發生繪製以及動畫執行過程當中,onDraw方法都會被調用到,避免在onDraw方法裏面執行復雜的操做,避免建立對象。對於那些沒法避免須要建立對象的狀況,咱們能夠考慮對象池模型,經過對象池來解決頻繁建立與銷燬的問題,可是這裏須要注意結束使用以後,須要手動釋放對象池中的對象。

下面是避免發生內存抖動的幾點建議:

  • 儘可能避免在循環體或者頻繁調用的函數內建立對象,應該把對象建立移到循環體外。
  • 注意自定義View的onDraw()方法會被頻繁調用,因此在這裏面不該該頻繁的建立對象。
  • 當須要大量使用Bitmap的時候,試着把它們緩存在數組中實現複用。
  • 對於可以複用的對象,同理可使用對象池將它們緩存起來。

更多閱讀

Android性能優化 (1)—— 內存溢出和內存泄漏的介紹

淺談App的性能優化

Android性能優化之包體壓縮,一篇文章教你玩轉優化App

BlockCannery-一個強大的Android程序調試工具,輕鬆幫你找出卡頓

相信本身,沒有作不到的,只有想不到的

微信公衆號:終端研發部

技術
相關文章
相關標籤/搜索