九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開(kāi)通VIP
Android內(nèi)存管理

前一段時(shí)間自己學(xué)習(xí)了下Android內(nèi)存管理相關(guān)的東西,在部門內(nèi)部做了一次技術(shù)分享。作為一個(gè)在公開(kāi)場(chǎng)合會(huì)靦腆,上不了臺(tái)面,表達(dá)能力也不行的人來(lái)說(shuō)是一個(gè)不小的進(jìn)步。一直很佩服墻內(nèi)墻外的牛人們堅(jiān)持寫博客和大家分享的精神。嗯,今天就將上次的技術(shù)分享寫在博客里面,希望對(duì)大家有幫助。

下面分為4個(gè)部分來(lái)闡述: 

  • Android內(nèi)存管理機(jī)制 
  • Android App中內(nèi)存管理優(yōu)化 
  • 檢測(cè)內(nèi)存使用情況 
  • 內(nèi)存泄漏 

一、Android系統(tǒng)內(nèi)存管理機(jī)制

1.Linux vs. Windows
兩者都能將物理內(nèi)存中長(zhǎng)時(shí)間不使用的內(nèi)容轉(zhuǎn)移到磁盤空間上,再次訪問(wèn)時(shí)才加載回內(nèi)存。
Windows只在應(yīng)用程序需要的時(shí)候才會(huì)分配內(nèi)存,不能充分充分利用內(nèi)存。
Linux充分利用物理內(nèi)存空間(RAM)及其高速讀寫特性,將程序調(diào)用過(guò)程中的硬盤數(shù)據(jù)讀入內(nèi)存,提高數(shù)據(jù)訪問(wèn)性能。 

Android是基于Linux系統(tǒng)的,繼承了Linux的很多優(yōu)秀特性。但是Android沒(méi)有可交換磁盤空間(swap space),所有的內(nèi)存都存在于RAM中,這使得Android系統(tǒng)釋放內(nèi)存的唯一方式就是釋放引用的對(duì)象。

2.Android進(jìn)程和內(nèi)存

Android進(jìn)程包含2種:
(1)Native進(jìn)程:采用C/C++實(shí)現(xiàn),不包含dalvik實(shí)例的進(jìn)程。/system/bin/目錄下面的文件運(yùn)行后都是以native進(jìn)程存在的。
(2)Java進(jìn)程:Android中運(yùn)行于dalvik虛擬機(jī)上的進(jìn)程。dalvik虛擬機(jī)的宿主進(jìn)程由fork()系統(tǒng)調(diào)用創(chuàng)建,所以每一個(gè)Java進(jìn)程都存在于一個(gè)Native進(jìn)程中。由于每個(gè)Java存在一個(gè)虛擬機(jī)實(shí)例,因此Java進(jìn)程內(nèi)存分配要比Native進(jìn)程復(fù)雜。 

3.Android中的java程序?yàn)樯度菀譕OM?
Android對(duì)dalvik的vm heapsize作了限制,當(dāng)Java進(jìn)程申請(qǐng)的內(nèi)存超過(guò)閾值時(shí),會(huì)拋出OOM異常。
程序發(fā)生OOM并不能說(shuō)明RAM不足,只能說(shuō)明是Java heap超出了dalvik vm heapsize的閾值。
當(dāng)RAM內(nèi)存不足時(shí),memory killer會(huì)殺掉低優(yōu)先級(jí)進(jìn)程,保證高優(yōu)先級(jí)進(jìn)程有更多內(nèi)存。 

Google之所以這樣設(shè)計(jì),處于以下考慮:
為了讓比較多的進(jìn)程同時(shí)常駐內(nèi)存,這樣程序啟動(dòng)時(shí)不需要每次都加載到內(nèi)存,能夠給用戶更快的響應(yīng)。通過(guò)限制每個(gè)應(yīng)用程序的內(nèi)存,使得Android系統(tǒng)內(nèi)存中同時(shí)常駐多個(gè)進(jìn)程。

4.如何繞過(guò)dalvik vm heapsize的限制
(1)創(chuàng)建子進(jìn)程
(2)使用JNI在native heap上申請(qǐng)內(nèi)存(推薦)
(3)使用RAM中的顯存空間

二、Android App中內(nèi)存管理優(yōu)化

1.Use services sparingly 

  • 盡量少用Service,當(dāng)后臺(tái)任務(wù)運(yùn)行完成時(shí)及時(shí)關(guān)閉Service
  • IntentService取代Service,當(dāng)后臺(tái)任務(wù)完成時(shí)自動(dòng)結(jié)束服務(wù)自身

原因:Service啟動(dòng)時(shí),Service所在進(jìn)程會(huì)保持運(yùn)行狀態(tài),Service所占用的內(nèi)存不會(huì)釋放,使得進(jìn)程占用資源過(guò)多,因此系統(tǒng)LRU cache中能同時(shí)保持的進(jìn)程數(shù)減少,應(yīng)用程序的切換變得更低效。由于沒(méi)有足夠的進(jìn)程來(lái)處理系統(tǒng)中的Service,也會(huì)導(dǎo)致系統(tǒng)穩(wěn)定性變差。

2.當(dāng)UI不可見(jiàn)或內(nèi)存緊張時(shí),釋放內(nèi)存:
Activity的回調(diào)方法onTrimMemory(int level)中根據(jù)level的不同釋放內(nèi)存。
進(jìn)程不在緩存中:

  • TRIM_MEMORY_RUNNING_MODERATE 應(yīng)用程序正在運(yùn)行,并且處于非killable狀態(tài),此時(shí)設(shè)備內(nèi)存低(low),系統(tǒng)主動(dòng)殺LRU緩存中的進(jìn)程
  • TRIM_MEMORY_RUNNING_LOW 應(yīng)用程序正在運(yùn)行,并且處于非killable狀態(tài),此時(shí)設(shè)備內(nèi)存很低(much lower),需要釋放沒(méi)用的資源
  • TRIM_MEMORY_RUNNING_CRITICAL 應(yīng)用程序正在運(yùn)行,但是系統(tǒng)已殺死LRU緩存中的大部分進(jìn)程,此時(shí)需要釋放所有不至關(guān)重要的資源。如果系統(tǒng)不能回收足夠的內(nèi)存,就會(huì)清掉LRU中所有的進(jìn)程以及服務(wù)進(jìn)程。 

進(jìn)程在LRU緩存中:

  • TRIM_MEMORY_BACKGROUND 系統(tǒng)低內(nèi)存下運(yùn)行,程序進(jìn)程位于LRU緩存列表的開(kāi)頭位置。雖然程序進(jìn)程被kill的概率不大,但是系統(tǒng)可能正在殺LRU中的進(jìn)程。你需要釋放容易恢復(fù)的資源以便程序進(jìn)程還在LRU list中,當(dāng)從其他App返回時(shí),能快速恢復(fù)現(xiàn)場(chǎng)。
  • TRIM_MEMORY_MODERATE 系統(tǒng)低內(nèi)存下運(yùn)行,程序進(jìn)程位于LRU緩存列表的中間位置。你的進(jìn)程被殺掉的可能性變大。
  • TRIM_MEMORY_COMPLETE 系統(tǒng)低內(nèi)存下運(yùn)行,程序進(jìn)程最先容易被系統(tǒng)殺死。你需要釋放所有對(duì)于恢復(fù)程序狀態(tài)不至關(guān)重要的資源。 

API14開(kāi)始有onTrimMemory()回調(diào);API 14以下使用的是onLowMemory(),等價(jià)于TRIM_MEMORY_COMPLETE

3.恰當(dāng)使用Bitmap
加載bitmap時(shí),盡量保證bitmap分辨率和屏幕分辨率匹配,對(duì)于大分辨率的bitmap需要進(jìn)行壓縮處理。 


(1) Android 2.3.x(API 10)及以下的系統(tǒng)
bitmap像素?cái)?shù)據(jù)實(shí)際存儲(chǔ)于native內(nèi)存中,在java heap中只是保留對(duì)象的引用,因此在java heap中內(nèi)部都顯示同一個(gè)大小。內(nèi)存回收需主動(dòng)調(diào)用recycle(),GC失效
(2) 在Android 3.0(API 11)及以上的系統(tǒng)
bitmap像素?cái)?shù)據(jù)存儲(chǔ)于java heap中,無(wú)需主動(dòng)調(diào)用recycle(),由GC管理內(nèi)存。
(3) 通過(guò)內(nèi)存分析工具調(diào)試bitmap內(nèi)存時(shí),在Android 3.0的系統(tǒng)上進(jìn)行,因?yàn)榇蟛糠謨?nèi)存分析工具只能分析java內(nèi)存

4.使用SparseArray,SparseBooleanArrayLongSparseArray等優(yōu)化的數(shù)據(jù)容器代替HashMap 

5.使用static const代替enum

6.非必要情況下,少用抽象

7.對(duì)于序列化數(shù)據(jù),使用nano protobuf

8.盡量少使用依賴注入框架

9.謹(jǐn)慎使用第三方庫(kù)

10.使用ProGuard去除不必要的代碼

11.apk打包簽名時(shí),使用zipalign工具對(duì)齊

12.使用多進(jìn)程
一般情況下,大多數(shù)應(yīng)用程序都不需要使用多進(jìn)程。只有對(duì)于需要在后臺(tái)和前臺(tái)同時(shí)運(yùn)行,并且前后臺(tái)單獨(dú)管理的程序才涉及到多進(jìn)程(如音樂(lè)播放器)。
使用多進(jìn)程方法:

<service android:name=".PlaybackService"     android:process=":background" />

一個(gè)空進(jìn)程占用大概1.4MB內(nèi)存,如果在該進(jìn)程中操作UI,內(nèi)存占用將是原來(lái)的好幾倍。因此如果使用多進(jìn)程,一般一個(gè)進(jìn)程用于UI,其他進(jìn)程不要有任何UI相關(guān)操作。

三、檢測(cè)內(nèi)存使用情況

1.分析Logcat信息

D/dalvikvm:<GC_Reason><Amount_freed>,<Heap_stats>,<External_memory_stats>,<Pause_time> 參數(shù)解釋:
  • GC_Reason 發(fā)生GC的原因(GC_CONCURRENT,GC_FOR_MALLOC,GC_HPROF_DUMP_HEAP,GC_EXPLICIT,GC_EXTERNAL_ALLOC)
  • Amount_freed 垃圾回收釋放的內(nèi)存
  • Heap_stats java堆內(nèi)存可用百分比(number of live objects)/(total heap size)
  • External_memory_stats (amount of allocated memory)/(limit at which collection will occur)
  • Pausing_time 取決于heap大小,對(duì)于并發(fā)操作可能會(huì)有2個(gè)pausing time

2.利用Eclipse的DDMS視圖自帶的內(nèi)存分析工具

  • 觀察heap內(nèi)存變化情況
    DDMS -> Update heap -> Cause GC
  • 跟蹤內(nèi)存分配情況
    DDMS -> Allocation Tracker -> Start Tracking -> GetAllocations
    跟蹤內(nèi)存分配的方法,可用定位到具體某個(gè)實(shí)例,某個(gè)線程,某個(gè)類,某個(gè)文件和某一行。

3.使用adb命令行 

adb shell dumpsys meminfo <package_name>

4.使用MAT內(nèi)存分析工具
下載eclipse插件memory analyze tool
操作DDMS -> Dump HPROF file -> save,分析Histigram view和Dominator tree內(nèi)容。

重要概念:shallow heap和retained heap

  • shallow heap 對(duì)象本身占用內(nèi)存大小
  • retained heap 通過(guò)釋放這個(gè)對(duì)象總共可以回收的內(nèi)存

四、內(nèi)存泄漏

1.GC原理


GC會(huì)選擇一些還存活的對(duì)象作為內(nèi)存遍歷的根節(jié)點(diǎn)GC Roots(如thread stack中的變量,JNI中的全局變量,zygote中的class loader對(duì)象等),對(duì)heap進(jìn)行遍歷,沒(méi)有被直接或間接遍歷到的引用會(huì)被GC回收,能被遍歷到的不能被回收。
內(nèi)存泄露:某些不再使用的對(duì)象被GC Roots引用,導(dǎo)致不能回收,使實(shí)際可使用內(nèi)存變小。

2.引起內(nèi)存泄露的因素
(1)長(zhǎng)時(shí)間保持對(duì)Activity,Context,View,Drawable和其他對(duì)象的引用
(2)非靜態(tài)內(nèi)部類
(3)持有對(duì)象的時(shí)間超出需要的時(shí)間

3.常見(jiàn)的內(nèi)存泄露
(1)非靜態(tài)內(nèi)部類的靜態(tài)實(shí)例
(2)Activity使用靜態(tài)成員
(3)Handler、HandlerThread使用時(shí)的問(wèn)題
(4)register某個(gè)對(duì)象后缺少對(duì)應(yīng)的unregister操作
(5)集合對(duì)象未清理,資源對(duì)象未關(guān)閉
(6)Dialog或PopupWindow未關(guān)閉引起的window leak
(7)不良代碼造成的壓力。如Bitmap使用不當(dāng);構(gòu)造adapter時(shí),沒(méi)有使用緩存的convertView;在循環(huán)方法中創(chuàng)建對(duì)象。

4.改進(jìn)建議 

  • 與View無(wú)關(guān)的操作盡量使用Application Context
  • 使用靜態(tài)內(nèi)部類
  • 靈活使用弱引用WeakReference
  • 對(duì)對(duì)象的持有時(shí)間不要超過(guò)其生命周期

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Android學(xué)習(xí)之 內(nèi)存管理機(jī)制與應(yīng)用內(nèi)存優(yōu)化
Android Training - 管理應(yīng)用的內(nèi)存
Android最佳性能實(shí)踐(一)
Android內(nèi)存泄漏分析及調(diào)試
Android性能優(yōu)化典范
ANDROID 探究oom內(nèi)幕
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服