自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

LeakCanary:檢測所有的內(nèi)存泄漏

移動開發(fā)
在Square的注冊過程中,我們在bitmap上 繪制了一個用戶的簽名。這個bitmap和設(shè)備的屏幕大小相當(dāng),在創(chuàng)建它的時候,我遇到了相當(dāng)數(shù)量的OOM導(dǎo)致的崩潰。這樣的問題怎么下手處理掉!

 原文: LeakCanary: Detect all memory leaks! 

  1. ava.lang.OutOfMemoryError 
  2.         at android.graphics.Bitmap.nativeCreate(Bitmap.java:-2
  3.         at android.graphics.Bitmap.createBitmap(Bitmap.java:689
  4.         at com.squareup.ui.SignView.createSignatureBitmap(SignView.java:121

沒人喜歡OutOfMemoryError

在Square的注冊過程中,我們在bitmap上 繪制了一個用戶的簽名。這個bitmap和設(shè)備的屏幕大小相當(dāng),在創(chuàng)建它的時候,我遇到了相當(dāng)數(shù)量的OOM導(dǎo)致的崩潰。

signature.png

我們試過了幾種方法,沒有一個解決了我們的問題:

  • 使用Bitmap.Config.ALPHA_8(簽名是不需要顏色的)

  • 捕獲OutOfMemoryError,觸發(fā)垃圾回收然后重試幾次(從GCUtils 獲得的啟發(fā))

  • 我們沒有考慮過將bitmap分配在堆內(nèi)存之外,那個時候Fresco 還沒出現(xiàn)。

我們看待問題的方式是不對的

bitmap的大小本身不是什么問題。當(dāng)內(nèi)存快要滿了的時候,OOM隨時隨地都可能發(fā)生。尤其是在創(chuàng)建大對象的時候更容易發(fā)生,比如bitmap。OOM一般代表著更深層次的問題:內(nèi)存泄漏。

什么是內(nèi)存泄漏?

有些對象只有有限的生命周期。當(dāng)它們的任務(wù)完成之后,它們將被垃圾回收。如果在對象的生命周期本該結(jié)束的時候,這個對象還被一系列的引用,這就會導(dǎo)致內(nèi)存泄漏。隨著泄漏的累積,app將消耗完內(nèi)存。

比如,在Activity.onDestroy()被調(diào)用之后,view樹以及相關(guān)的bitmap都應(yīng)該被垃圾回收。如果一個正在運行的后臺線程繼續(xù)持有這個Activity的引用,那么相關(guān)的內(nèi)存將不會被回收,這最終將導(dǎo)致OutOfMemoryError崩潰。

尋找內(nèi)存泄漏

尋找內(nèi)存泄漏是一個人工操作的過程,在Raizlabs的 Wrangling Dalvik 系列中描述得很清楚。

下面是關(guān)鍵的步驟:

  1. 通過 BugsnagCrashlytics, 或者 Developer Console了解OOM

  2. 主動重現(xiàn)問題。你可能需要買或者借或者偷一個遭遇了崩潰的特殊設(shè)備(并不是所有的設(shè)備上都會發(fā)生內(nèi)存泄漏!)。你還需要找出是什么串在一起導(dǎo)致了內(nèi)存泄漏。

  3. 當(dāng)OOM出現(xiàn)時進(jìn)行堆轉(zhuǎn)儲(dump the heap)(這里介紹了如何做).

  4. 使用MAT或YourKit內(nèi)存檢測工具檢測內(nèi)存的變化,并找出哪個對象應(yīng)該被垃圾回收;

  5. 從那個對象到GC roots推斷最短的強引用路徑;

  6. 在路徑中找出不存在的引用,并修復(fù)memory leak;

要是有一個庫可以為你做完所有的事情,讓你專注于修復(fù)內(nèi)存泄漏的問題,那該有多好。

LeakCanary介紹

LeakCanary 是一個開源的在debug版本中檢測內(nèi)存泄漏的java庫。

讓我們來看看一個cait的例子:

  1. class Cat { 
  2. class Box { 
  3.   Cat hiddenCat; 
  4. class Docker { 
  5.   static Box container; 
  6.   
  7. // ... 
  8.   
  9. Box box = new Box(); 
  10. Cat schrodingerCat = new Cat(); 
  11. box.hiddenCat = schrodingerCat; 
  12. Docker.container = box; 

創(chuàng)建一個RefWatcher實例,然后給它一個對象讓它觀察:

 
  1. // We expect schrodingerCat to be gone soon (or not), let's watch it. 
  2. refWatcher.watch(schrodingerCat); 

當(dāng)檢測出泄漏的時候,你會自動得到一個漂亮的泄漏線索:

  1. * GC ROOT static Docker.container 
  2. * references Box.hiddenCat 
  3. * leaks Cat instance 

我們知道你的時間寶貴,因此我們讓它非常好設(shè)置。只需幾行代碼,LeakCanary就能自動檢測Activity的泄漏:

  1. public class ExampleApplication extends Application { 
  2.   @Override public void onCreate() { 
  3.     super.onCreate(); 
  4.     LeakCanary.install(this); 
  5.   } 

 

當(dāng)內(nèi)存不足時,會有一個通知和良好的展示界面:

leaktrace.png

結(jié)論

在啟用LeakCanary之后,我們發(fā)現(xiàn)和修復(fù)了許多內(nèi)存泄漏的問題。我們甚至發(fā)現(xiàn)了一些 Android SDK中的泄漏。

結(jié)果是非常令人驚奇的,我們現(xiàn)在減少了94%的oom崩潰問題。

oom_rate.png

如果你想終結(jié)OOM崩潰,現(xiàn)在就安裝LeakCanary!

責(zé)任編輯:倪明 來源: Square engineering blog
相關(guān)推薦

2023-10-31 16:40:38

LeakCanary內(nèi)存泄漏

2017-05-23 21:00:47

Android開源項目內(nèi)存泄漏

2018-12-07 10:52:08

內(nèi)存泄漏方法

2010-09-25 11:07:45

Java內(nèi)存泄漏

2009-06-16 11:20:22

內(nèi)存泄漏

2011-06-16 09:28:02

C++內(nèi)存泄漏

2024-07-03 11:28:15

2010-09-26 15:38:33

JVM內(nèi)存泄漏

2022-09-28 10:35:31

JavaScript代碼內(nèi)存泄漏

2021-03-04 17:21:49

內(nèi)存檢測泄漏

2015-04-17 10:35:51

c++c++程序內(nèi)存泄漏檢測代碼

2024-03-11 08:22:40

Java內(nèi)存泄漏

2023-12-18 10:45:23

內(nèi)存泄漏計算機服務(wù)器

2012-02-22 21:28:58

內(nèi)存泄漏

2024-12-05 08:58:47

2015-03-30 11:18:50

內(nèi)存管理Android

2020-06-08 09:18:59

JavaScript開發(fā)技術(shù)

2019-01-30 18:24:14

Java內(nèi)存泄漏編程語言

2021-08-09 09:54:37

內(nèi)存泄漏JS 阿里云

2021-08-05 15:28:22

JS內(nèi)存泄漏
點贊
收藏

51CTO技術(shù)棧公眾號