免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Android內存性能優(yōu)化
Android內存性能優(yōu)化(內部資料總結)
2014-05-23     我來說兩句    來源:Android內存性能優(yōu)化(內部資料總結)  
收藏   
我要投稿

剛入門的童鞋肯能都會有一個疑問,Java不是有虛擬機了么,內存會自動化管理,我們就不必要手動的釋放資源了,反正系統(tǒng)會給我們完成。其實Java中沒有指針的概念,但是指針的使用方式依然存在,一味的依賴系統(tǒng)的gc,很容易就造成了內存的浪費。

Java基于垃圾回收的內存機制

Java的內存管理機制會自動回收無用對象所占用的內存,減輕手工管理內存的負擔

1、C/C++: 從申請、使用、釋放都需要手工管理

2、Java:無用的對象的內存會被自動回收



什么樣的對象是無用的對象

1、Java通過引用來操作一個具體的對象,引用類似于C 中的指針。一個對象可以持有其他對象的引用。

2、從一組根對象(GC Roots)開始,按對象之前的引用關系遍歷所有對象,在遍歷過程中標記所有的可達對象。如果一個對象由根對象出發(fā)不可達,則將它作為垃圾收集。

GCRoot 都有哪些?

1、 Class:由系統(tǒng)的類加載器加載的類對象

2、 Static Fields

3、 Thread:活著的線程

4、 Stack Local: java方法的局部變量或參數(shù)

5、 JNI Local: JNI方法中的局部引用

6、 JNI Global: 全局的JNI引用

7、 Monitor used: 用于同步的監(jiān)控對象

8、Help by VM: 用于JVM特殊目的由GC保留的對象



Java程序中的內存泄漏

對象的內存在分配之后無法通過程序的執(zhí)行邏輯釋放對該對象的引用,不能被回收該對象所占內存

內存泄漏的危害

1、 引起OutOfMemoryError

2、 內存占用高時JVM虛擬機會頻繁觸發(fā)GC, 影響程序響應速度

3、內存占用大的程序容易被各種清理優(yōu)化程序中止,用戶也更傾向于卸載這些程序

Android應用的開發(fā)語言為Java,每個應用最大可使用的堆內存受到Android系統(tǒng)的限制

Android每一個應用的堆內存大小有限

1、 通常的情況為16M-48M

2、 通過ActivityManager的getMemoryClass()來查詢可用堆內存限制

3、3.0(HoneyComb)以上的版本可以通過largeHeap=“true”來申請更多的堆內存

Nexus S(4.2.1):normal 192, largeHeap 512

4、如果試圖申請的內存大于當前余下的堆內存就會引發(fā)OutOfMemoryError()

5、應用程序由于各方面的限制,需要注意減少內存占用,避免出現(xiàn)內存泄漏。

用MAT工具來檢測內存泄漏

在試圖窗口中新建一個Memory Analysis會出現(xiàn)一個

沒有的可以去http://www.eclipse.org/mat/downloads.php安裝一下MAT

在Android 的調試環(huán)境DDMS下,找到Heap dump

Dump下當前內存中的鏡像文件,*****.hprof


能清楚的看到每一個部分暫用的內存大小。

也可以切換試圖,group查看不同包不同類的占用細節(jié)。

Heap dump

包含了觸發(fā)Heap dump生成的時刻Java進程的內存快照,主要內容為各個Java類和對象在堆內存中的分配情況

Memory Analyzer Tool (MAT)

常見內存泄露原因

Context對象泄漏

1、如果一個類持有Context對象的強引用,就需要檢查其生存周期是否比Context對象更長。否則就可能發(fā)生Context泄漏。

2、View持有其創(chuàng)建所在Context對象的引用,如果將View對象傳遞給其它生存周期比View所在Context更長的強引用,就可能會引起內存泄漏。

例如View#setTag(int, Object)的內存泄漏https://code.google.com/p/android/issues/detail?id=18273

3、把Context對象賦給static變量。

避免Context對象泄漏Checklist

1、檢查所有持有對Context對象強引用的對象的生命周期是否超出其所持有的Context對象的生命周期。

2、檢查有沒有把View傳出到View所在Context之外的地方,如果有的話就需要檢查生命周期。

3、工具類中最好不要有Context成員變量,盡量在調用函數(shù)時直接通過調用參數(shù)傳入。如果必須有Context成員變量時,可以考慮使用WeakReference來引用Context對象。

4、View持有其創(chuàng)建所在Context對象的引用,如果將View對象傳遞給其它生存周期比View所在Context更長的強引用,就可能會引起內存泄漏。

5、 檢查把Context或者View對象賦給static變量的地方,看是否有Context泄漏。

6、檢查所有把View放入容器類的地方(特別是static容器類),看是否有內存泄漏。7、使用WeakHashMap也需要注意有沒有value-key的引用。

7、盡量使用ApplicationContext。

Handler對象泄漏

1、發(fā)送到Handler的Message實際上是加入到了主線程的消息隊列等待處理,每一個Message持有其目標Handler的強引用。

如我們通常使用的匿名內部類Handler

1
2
3
4
5
6
<span style="font-size:18px;">HandlermHandler = new Handler() {
    @Override
    public voidhandleMessage(Message msg) {
       mImageView.setImageBitmap(mBitmap);
    }
}</span>


上面是一段簡單的Handler的使用。當使用內部類(包括匿名類)來創(chuàng)建Handler的時候,Handler對象會隱式地持有一個外部類對象(通常是一個Activity)的引用,因為View會依附著一個Activity。而Handler通常會伴隨著一個耗時的后臺線程(例如從網(wǎng)絡拉取圖片)一起出現(xiàn),這個后臺線程在任務執(zhí)行完畢(例如圖片下載完畢)之后,通過消息機制通知Handler,然后Handler把圖片更新到界面。然而,如果用戶在網(wǎng)絡請求過程中關閉了Activity,正常情況下,Activity不再被使用,它就有可能在GC檢查時被回收掉,但由于這時線程尚未執(zhí)行完,而該線程持有Handler的引用(不然它怎么發(fā)消息給Handler?),這個Handler又持有Activity的引用,就導致該Activity無法被回收(即內存泄露),直到網(wǎng)絡請求結束(例如圖片下載完畢)。另外,如果你執(zhí)行了Handler的postDelayed()方法,該方法會將你的Handler裝入一個Message,并把這條Message推到MessageQueue中,那么在你設定的delay到達之前,會有一條MessageQueue -> Message -> Handler -> Activity的鏈,導致你的Activity被持有引用而無法被回收。

當然,應為是Handler對外部持有引用的原因,我們就可以將Activity設置為一個弱引用,在不必要的時候,不再執(zhí)行內部方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<span style="font-size:18px;">/**
 * @author zhoushengtao
 * @since 2013-12-16 下午3:25:36
 */
  
import android.app.Activity;
importandroid.content.Context;
importandroid.os.Handler;
importandroid.os.Message;
  
importjava.lang.ref.WeakReference;
  
publicclass WeakRefHandler extends Handler
{
    WeakReference<context> mWeakContext;
  
    public WeakRefHandler(Context context)
    {
        mWeakContext = newWeakReference<context>(context);
    }
  
    @Override
    public void handleMessage(Message msg)
    {
        if((mWeakContext.get() instanceofActivity )&& ((Activity)mWeakContext.get()).isFinishing())
                return ;
        if(mWeakContext==null){
            return ;
        }
        super.handleMessage(msg);
    }
}</context></context></span>


2、Non-staticinner class 和anonymous class持有其outer class的引用。

Drawable.Callback引起的內存泄漏

Drawable對象持有Drawable.callback的引用。當把一個Drawable對象設置到一個View時,Drawable對象會持有該View的引用作為Drawable.Callback



避免Drawable.Callback引起內存泄漏

盡量不要在static成員中保存Drawable對象

對于需要保存的Drawable對象, 在需要時調用Drawable#setCallback(null).

其他內存泄漏<喎?"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjwvcD4KPHAgYWxpZ249"left"> 1、Android DigitalClock引起的內存泄漏http://code.google.com/p/android/issues/detail?id=17015

2、使用Map容器類時,作為Key 的類沒有正確的實現(xiàn)hashCode和equal函數(shù)

其他內存泄漏

JNI程序中的內存泄漏

1、 Malloc/free。

2、 JNI Global reference

Thread-Local Variable

1、 相當于Thread對象的成員變量, 可以存儲線程相關的狀態(tài)

2、 如果thread是alive狀態(tài),那么Thread-Local中的對象就無法被GC。

進程內存占用監(jiān)測工具

Dumpsys

$ dumpsys meminfo [pid]

Procrank + Shell腳本

#procrank

1、 VSS - Virtual Set Size 虛擬耗用內存(包含共享庫占用的內存)

2、 RSS - Resident Set Size 實際使用物理內存(包含共享庫占用的內存)

3、 PSS - Proportional Set Size 實際使用的物理內存(比例分配共享庫占用的內存)

4、 USS - Unique Set Size 進程獨自占用的物理內存(不包含共享庫占用的內存)

Shell腳本

#!/bin/bash

while true; do

adbshell procrank " grep "com.qihoo360.mobilesafe"

sleep1

done

當然,部分機型的sh都是經(jīng)過第三方手機商精簡過的,很多命令都用不了。Procrank,就是一個經(jīng)常被精簡掉的命令。

鑒于此:

自己寫了一個小工具,檢測內存的實時變化,

Github地址:https://github.com/stchou/JasonTest


小結

1. 保存對象前要三思

I. 對象本身有無隱含的引用

II. 保存后何時能夠回收

2. 要了解常見的隱含引用

I. anonymous class outer class

II. View to context

3. 要通過各種工具檢查內存占用是否有異常

4. 創(chuàng)建大對象時,要檢查它的生命周期


/**
* @author zhoushengtao(周圣韜)
* @since 2014年5月21日 下午6:18:29

本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Android App定位和規(guī)避內存泄露方法研究
Android內存泄漏簡介
Android中內存泄漏與OOM避免措施總結
Android常見內存泄露,學會這六招大大優(yōu)化APP性能
深入Android內存泄露
內存泄漏研究 | Jason's Blog
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服