国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

LeakCanary傻瓜式的內(nèi)存泄露檢測(cè)工具

shixinzhang / 2777人閱讀

摘要:另一種方式就是是一個(gè)簡(jiǎn)單的,方便的內(nèi)存檢測(cè)工具,可以輕易的發(fā)現(xiàn)內(nèi)存問題,還會(huì)生成更加簡(jiǎn)單清晰的報(bào)告。是一個(gè)開源的檢測(cè)內(nèi)存泄露的庫。

在開發(fā)Android應(yīng)用的過程中如果需要處理圖片或者大量數(shù)據(jù)的時(shí)候,就有可能會(huì)遇到OOMjava.lang.OutOfMemoryError),一般出現(xiàn)最多的是在創(chuàng)建Bitmap上,也有可能是在內(nèi)存中處理了大量的數(shù)據(jù)上。出現(xiàn)OOM應(yīng)用會(huì)直接崩潰,即使沒有出現(xiàn)OOM,內(nèi)存使用過大的時(shí)候應(yīng)用也會(huì)出現(xiàn)卡頓。所以內(nèi)存的優(yōu)化在開發(fā)Android應(yīng)用時(shí)是一個(gè)比較重要的任務(wù)。
一般會(huì)針對(duì)Bitamp的內(nèi)存優(yōu)化有下面幾種方式:

1. 增加進(jìn)程的內(nèi)存
2. 使用Bitmap.Config.ALPHA_8(圖片失真)
3. 顯示的調(diào)用System.gc()
4. catch Exception
5. 調(diào)用bitmap.recycle()
6. 縮小bitmap的大小(如果是讀取的原圖是一個(gè)大圖應(yīng)該先采用這種方式,Bitmap如果是剛好適配屏幕的就不需要縮小了)
7. 使用弱引用和軟引用(google已經(jīng)不建議使用了,Android的GC效率非常高,只要保證對(duì)象沒有被引用即可)

但是我們忽略掉一個(gè)問題就是什么造成了OOM
一般來說發(fā)生OOM崩潰的地方不一定是內(nèi)存泄露的地方,崩潰的原因有可能是Activity造成的內(nèi)存泄露,也可能是操作數(shù)據(jù)庫造成的內(nèi)存泄露,當(dāng)內(nèi)存已經(jīng)非常接近峰值的時(shí)候,這個(gè)時(shí)候恰巧要?jiǎng)?chuàng)建一個(gè)Bitmap對(duì)象就會(huì)發(fā)生OOM(Bitmap對(duì)象占用的內(nèi)存比較大)。
是什么原因造成了內(nèi)存泄露呢?

內(nèi)存泄露

我們知道Android中每個(gè)對(duì)象都有自己的生命周期,比如Activity的生命周期最后會(huì)調(diào)用onDestroy方法做銷毀處理,但如果使用Activity中調(diào)用了類似于Toast這種對(duì)象,就會(huì)把這個(gè)Activity的引用傳給了Toast,而Toast的生命周期不會(huì)隨著Activity的銷毀而銷毀,這樣就造成了Activity的內(nèi)存泄露,它會(huì)被Toast對(duì)象引用,無法被銷毀。
常見的內(nèi)存泄露形成的原因:

Toast持有Activity的引用

數(shù)據(jù)庫游標(biāo)Cursor沒有關(guān)閉

Adapter沒有復(fù)用convertView

對(duì)象被生命周期更長(zhǎng)的對(duì)象引用,Activity被靜態(tài)集合引用

....

那如何知道應(yīng)用的內(nèi)存有沒有出現(xiàn)泄露呢?

監(jiān)控內(nèi)存的方式

Heap Dump:常見的內(nèi)存監(jiān)控方式是Heap DumpHeap Dump是一種在Java中比較常用的檢測(cè)內(nèi)存的方式:

簡(jiǎn)單來說就是我們?cè)谝粋€(gè)初始狀態(tài)A, 在這個(gè)時(shí)候Dump一次內(nèi)存,在做了一些操作之后回到狀態(tài)A,再Dump一次內(nèi)存。

對(duì)兩次Dunp的內(nèi)存數(shù)據(jù)(hprof)使用分析工具做分析(MAT),根據(jù)分析的結(jié)果就能知道是否存在內(nèi)存泄露,這種方式比較復(fù)雜和繁瑣并不是特別易用。

Moitors:這是Android SDK 自帶的內(nèi)存監(jiān)控工具,Monitors能檢測(cè)到內(nèi)存的變化,比如內(nèi)存是增加還是減少。
打開一個(gè)Activity會(huì)導(dǎo)致內(nèi)存增加,關(guān)閉一個(gè)Activity會(huì)導(dǎo)致內(nèi)存減少,反復(fù)的做這樣的操作,如果每次打開一個(gè)Activity再關(guān)閉之后增加的內(nèi)存不會(huì)減少就說明這個(gè)Activity有可能有內(nèi)存泄露,再借助log輔助進(jìn)行檢測(cè),就可以發(fā)現(xiàn)內(nèi)存泄露的問題,
這種方式的缺點(diǎn)是并不是特別的準(zhǔn)確,因?yàn)閮?nèi)存的釋放和對(duì)象的生命周期有關(guān)也和GC的調(diào)度有關(guān)。
另一種方式就是LeakCanary,LeakCanary是一個(gè)簡(jiǎn)單的,方便的內(nèi)存檢測(cè)工具,可以輕易的發(fā)現(xiàn)內(nèi)存問題,還會(huì)生成更加簡(jiǎn)單清晰的報(bào)告。

LeakCanary

LeakCanary是一個(gè)開源的檢測(cè)內(nèi)存泄露的java庫。項(xiàng)目地址:https://github.com/square/lea...
LeakCanary實(shí)際上就是在本機(jī)上自動(dòng)做了Heap dump,對(duì)生成的hprof文件進(jìn)行分析,展示分析的結(jié)果。和手工分析Heap Dump的方式得到的結(jié)果是一樣的。只不過這部分的工作完全自動(dòng)化完成了。
下面是一個(gè)LeakCanary的結(jié)果截圖:

從上圖可以看到,LeakCanary能清晰簡(jiǎn)單的展示出那里有內(nèi)存泄露的問題。那LeakCanary如何使用呢?

集成LeakCanary

build.gradle添加依賴:

dependencies {
   debugCompile "com.squareup.leakcanary:leakcanary-android:1.3.1"
   releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:1.3.1"
   testCompile "com.squareup.leakcanary:leakcanary-android-no-op:1.3.1"
 }

使用LeakCanary對(duì)應(yīng)用進(jìn)行檢測(cè)它會(huì)影響程序的性能,尤其是在做Heap dump分析操作時(shí),因此需要在依賴?yán)锩嬷付▽?duì)應(yīng)的版本,debug的時(shí)候才進(jìn)行分析,release的時(shí)候不能進(jìn)行分析。
debugCompile可以使用檢測(cè)版本:

com.squareup.leakcanary:leakcanary-android

releaseCompile使用no-op模式,即No Operation Performed就是不會(huì)把對(duì)應(yīng)的類庫編譯,指定類庫為無用的指令:

com.squareup.leakcanary:leakcanary-android-no-op

這樣就可以指定LeakCanary為無用指令,不會(huì)在release的時(shí)候進(jìn)行編譯。
Application中加入分析Activity的代碼:

public class ExampleApplication extends Application {

  @Override public void onCreate() {
    super.onCreate();
    LeakCanary.install(this);
  }
}

這樣就可以檢測(cè)所有Activity的內(nèi)存泄露了。LeakCanary內(nèi)部實(shí)現(xiàn)使用了ActivityLifecycleCallbacks方法監(jiān)聽所有Activity的生命周期。
除了Activity會(huì)發(fā)生內(nèi)存泄露以外,其他對(duì)象也有可能會(huì)出現(xiàn)內(nèi)存泄露,如果對(duì)其他對(duì)象進(jìn)行檢測(cè)呢?

檢測(cè)其他對(duì)象

LeakCanary中提供了RefWatcher類,可以用來監(jiān)控所有的對(duì)象。
首先實(shí)例化RefWatcher:

public static RefWatcher sRefWatcher=LeakCanary.install(mContext);

對(duì)于監(jiān)控的對(duì)象使用:

sRefWatcher.watch(this)

一般我們是在對(duì)象銷毀的時(shí)候?qū)?duì)象進(jìn)行監(jiān)控,比如內(nèi)部實(shí)現(xiàn)的對(duì)于Activity的監(jiān)控的原理如下:

private final ActivityLifecycleCallbacks lifecycleCallbacks = new ActivityLifecycleCallbacks() {
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        }

        public void onActivityStarted(Activity activity) {
        }

        public void onActivityResumed(Activity activity) {
        }

        public void onActivityPaused(Activity activity) {
        }

        public void onActivityStopped(Activity activity) {
        }

        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }

        public void onActivityDestroyed(Activity activity) {
            ActivityRefWatcher.this.onActivityDestroyed(activity);
        }
    };

只是在onActivityDestroyed的時(shí)候才對(duì)于activity進(jìn)行監(jiān)控即可。
檢測(cè)到了內(nèi)存泄露,如果解決呢?

解決內(nèi)存泄露

一般情況內(nèi)存泄露的原因都是由于引用的使用不當(dāng)造成的,Android GC能夠保證回收循環(huán)引用(如果一個(gè)循環(huán)引用沒有外部引用時(shí)就會(huì)被回收),且Android GC效率很高,當(dāng)然GC的算法本身也在不停的改進(jìn)。
一般情況下只需要盡量避免錯(cuò)誤的引用方式帶來的內(nèi)存泄露問題即可:

生命周期長(zhǎng)的對(duì)象引用生命周期短的對(duì)象,比如static的對(duì)象群引用Activity

使用Application的Context對(duì)象,而不是Activity的Context

避免非靜態(tài)類的內(nèi)部類對(duì)于類的隱式引用,使用靜態(tài)的內(nèi)部類

使用Android的緩存機(jī)制,比如ListView的復(fù)用機(jī)制

手動(dòng)關(guān)閉資源,比如Curous的關(guān)閉

registerReceiver和unRegisterReceiver成對(duì)出現(xiàn)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/65757.html

相關(guān)文章

  • 內(nèi)存泄漏優(yōu)化

    摘要:內(nèi)存泄漏會(huì)造成什么影響它是造成應(yīng)用程序的主要原因之一。靜態(tài)變量引用不當(dāng)會(huì)導(dǎo)致內(nèi)存泄漏靜態(tài)變量和會(huì)導(dǎo)致內(nèi)存泄漏,在下面這段代碼中對(duì)的和設(shè)置為靜態(tài)對(duì)象,從而產(chǎn)生內(nèi)存泄漏。 目錄介紹: 1.什么是內(nèi)存泄漏 2.內(nèi)存泄漏造成什么影響 3.內(nèi)存泄漏檢測(cè)的工具有哪些 4.關(guān)于Leakcanary使用介紹 5.Leakcanary捕捉常見的內(nèi)存泄漏及解決辦法 5.0.1 錯(cuò)誤使用單例造成的內(nèi)存...

    icyfire 評(píng)論0 收藏0
  • 內(nèi)存泄漏優(yōu)化

    摘要:內(nèi)存泄漏造成什么影響它是造成應(yīng)用程序的主要原因之一。造成的內(nèi)存泄漏早時(shí)期的時(shí)候處理耗時(shí)操作多數(shù)都是采用的方式,后來逐步被取代,直到現(xiàn)在采用的方式來處理異步。 目錄介紹: 01.什么是內(nèi)存泄漏 02.內(nèi)存泄漏造成什么影響 03.內(nèi)存泄漏檢測(cè)的工具有哪些 04.關(guān)于Leakcanary使用介紹 05.錯(cuò)誤使用單例造成的內(nèi)存泄漏 06.Handler使用不當(dāng)造成內(nèi)存泄漏 07.Thread...

    fanux 評(píng)論0 收藏0
  • Android內(nèi)存泄漏優(yōu)化

    摘要:內(nèi)存泄漏造成什么影響它是造成應(yīng)用程序的主要原因之一。因此總結(jié)來看,線程產(chǎn)生內(nèi)存泄露的主要原因有兩點(diǎn)線程生命周期的不可控。造成的內(nèi)存泄漏早時(shí)期的時(shí)候處理耗時(shí)操作多數(shù)都是采用的方式,后來逐步被取代,直到現(xiàn)在采用的方式來處理異步。 目錄介紹: 01.什么是內(nèi)存泄漏 02.內(nèi)存泄漏造成什么影響 03.內(nèi)存泄漏檢測(cè)的工具有哪些 04.關(guān)于Leakcanary使用介紹 05.錯(cuò)誤使用單例造成的內(nèi)...

    sourcenode 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<