999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

基于Android的內(nèi)存泄漏與溢出研究

2018-03-10 00:30:35何群芳時(shí)招軍
軟件導(dǎo)刊 2018年2期

何群芳+時(shí)招軍

摘 要:內(nèi)存的泄漏與溢出是在進(jìn)行Android開(kāi)發(fā)時(shí)最常見(jiàn)且棘手的問(wèn)題之一。為了提高Android開(kāi)發(fā)的質(zhì)量和效率,總結(jié)了Android的內(nèi)存泄漏與溢出的常見(jiàn)類(lèi)型和解決方法。內(nèi)存泄漏的常見(jiàn)類(lèi)型有集合類(lèi)泄漏、傳入Activity的Context造成的內(nèi)存泄漏、非靜態(tài)內(nèi)部類(lèi)創(chuàng)建靜態(tài)實(shí)例和線(xiàn)程造成的內(nèi)存泄漏等;內(nèi)存溢出的常見(jiàn)類(lèi)型有由強(qiáng)引用造成的內(nèi)存溢出、由大量圖片顯示導(dǎo)致的內(nèi)存溢出、從數(shù)據(jù)庫(kù)中取出大量數(shù)據(jù)造成的內(nèi)存溢出、代碼中存在死循環(huán)或循環(huán)產(chǎn)生過(guò)多重復(fù)對(duì)象實(shí)體造成的內(nèi)存溢出等,并提出了由圖片造成的內(nèi)存溢出的新的解決方法。

關(guān)鍵詞:內(nèi)存管理;Android;內(nèi)存泄漏;內(nèi)存溢出

DOIDOI:10.11907/rjdk.172379

中圖分類(lèi)號(hào):TP301

文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1672-7800(2018)002-0050-03

0 引言

Java的內(nèi)存管理即為對(duì)象的分配和釋放問(wèn)題。在Java中,程序員需要通過(guò)關(guān)鍵字new為每個(gè)對(duì)象申請(qǐng)內(nèi)存空間(基本類(lèi)型除外),所有對(duì)象都在堆(Heap)中分配空間。而對(duì)象的釋放由GC決定和執(zhí)行。該方式確實(shí)簡(jiǎn)化了程序員的工作,但同時(shí)也加大了JVM的工作量。因?yàn)镚C為了能夠正確地釋放對(duì)象,必須監(jiān)控每一個(gè)對(duì)象的運(yùn)行狀態(tài),包括對(duì)象的申請(qǐng)、引用、被引用、賦值等[1-4]。

在Java中,內(nèi)存泄漏就是存在一些被分配的對(duì)象,這些對(duì)象存在以下兩個(gè)特點(diǎn):首先,這些對(duì)象是可達(dá)的,即在有向圖中,存在通路可以與其相連(也即是說(shuō)仍存在對(duì)該對(duì)象的引用);其次,這些對(duì)象是無(wú)用的,即程序以后不會(huì)再使用這些對(duì)象。如果滿(mǎn)足這兩個(gè)條件,這些對(duì)象即可判定為Java中的內(nèi)存泄漏。內(nèi)存泄漏造成的后果在于內(nèi)存泄漏堆積,如果一直存在內(nèi)存泄漏,最終會(huì)導(dǎo)致越來(lái)越多內(nèi)存無(wú)法回收而又不能被利用,最終可用內(nèi)存越來(lái)越少。內(nèi)存溢出是程序占用的內(nèi)存大小超過(guò)了虛擬機(jī)(DVM)的允許值,而造成內(nèi)存溢出的最主要原因是高質(zhì)量圖片的大量出現(xiàn)。通過(guò)對(duì)Java內(nèi)存分配、內(nèi)存管理和垃圾回收原理的理解,總結(jié)導(dǎo)致內(nèi)存泄漏和內(nèi)存溢出的常見(jiàn)原因,并提出相應(yīng)預(yù)防措施,可有效提升程序質(zhì)量。

1 內(nèi)存泄漏與內(nèi)存溢出常見(jiàn)類(lèi)型與解決方法

內(nèi)存泄漏(Memory Leak)是指程序中己動(dòng)態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無(wú)法釋放,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致程序運(yùn)行速度減慢甚至系統(tǒng)崩潰等嚴(yán)重后果;內(nèi)存溢出(Out of Memory)通俗理解就是內(nèi)存不夠,通常在運(yùn)行大型軟件或游戲時(shí),軟件或游戲所需的內(nèi)存遠(yuǎn)遠(yuǎn)超出了主機(jī)內(nèi)安裝的內(nèi)存所能承受的大小,稱(chēng)為內(nèi)存溢出。此時(shí)軟件或游戲無(wú)法運(yùn)行,系統(tǒng)會(huì)提示內(nèi)存溢出,有時(shí)甚至?xí)詣?dòng)關(guān)閉軟件,重啟電腦或軟件后釋放掉部分內(nèi)存,又可以正常運(yùn)行該軟件。

1.1 內(nèi)存泄漏常見(jiàn)類(lèi)型與解決方法

1.1.1 集合類(lèi)泄漏

集合類(lèi)如果僅有添加元素的方法,而沒(méi)有相應(yīng)的刪除機(jī)制,可能導(dǎo)致內(nèi)存被占用。如果該集合類(lèi)是全局性的變量 (比如類(lèi)中的靜態(tài)屬性、全局性的 map 等即有靜態(tài)引用或 final 一直指向它),則沒(méi)有相應(yīng)的刪除機(jī)制,很可能導(dǎo)致集合占用的內(nèi)存只增不減,這就是集合類(lèi)泄漏。

解決方法:給集合類(lèi)添加相應(yīng)的刪除機(jī)制,最簡(jiǎn)單的方法是直接將集合置為null。

1.1.2 傳入Activity的Context造成的內(nèi)存泄漏

因?yàn)锳ctivity的生命周期可能比引用該Activity的生命周期短,所以即使該Activity被銷(xiāo)毀,依然處于被引用狀態(tài),GC無(wú)法回收,造成內(nèi)存泄漏。例如在static的工具類(lèi)中,在創(chuàng)建數(shù)據(jù)庫(kù)或打開(kāi)數(shù)據(jù)庫(kù)、開(kāi)啟系統(tǒng)服務(wù)與廣播時(shí)以及創(chuàng)建單例等情況下傳入Activity的Context,即使Activity被銷(xiāo)毀,GC依然無(wú)法回收該Activity所占用的資源,這就是由傳入Activity的Context造成的內(nèi)存泄漏。

解決方法:如果需要傳入Context,可以改用Application的Context,即getApplicationContext()。當(dāng)然,Application的Context也不是萬(wàn)能的,基本上除了start a activity和show a dialog需要Activity的Context之外,其他的都可以用Application的Context替代。

1.1.3 非靜態(tài)內(nèi)部類(lèi)創(chuàng)建靜態(tài)實(shí)例與線(xiàn)程造成的內(nèi)存泄漏

非靜態(tài)內(nèi)部類(lèi)默認(rèn)持有外部類(lèi)的引用,而該非靜態(tài)內(nèi)部類(lèi)又創(chuàng)建了一個(gè)靜態(tài)實(shí)例,該實(shí)例的生命周期和應(yīng)用長(zhǎng)度相同,將導(dǎo)致了該靜態(tài)實(shí)例一直會(huì)持有該Activity的引用,導(dǎo)致Activity的內(nèi)存資源不能正常回收。線(xiàn)程和非靜態(tài)內(nèi)部類(lèi)相似。

解決方法:將非靜態(tài)的內(nèi)部類(lèi)改為靜態(tài)的內(nèi)部類(lèi),并將對(duì)Activity的引用改為弱引用,使內(nèi)部類(lèi)和線(xiàn)程的生命周期脫離Activity的生命周期,并且當(dāng)GC進(jìn)行回收時(shí),可以回收被弱引用的Activity等[5-8]。

1.2 內(nèi)存溢出常見(jiàn)類(lèi)型與解決方法

1.2.1 由強(qiáng)引用造成的內(nèi)存溢出

若所有的引用都是強(qiáng)引用,則大量?jī)?nèi)存會(huì)被占用,最終導(dǎo)致內(nèi)存溢出。

解決方法:使用弱引用或軟引用,軟引用的對(duì)象在內(nèi)存不足時(shí)可被GC回收,弱引用的對(duì)象在垃圾回收時(shí)可被回收。

1.2.2 由大量圖片顯示導(dǎo)致的內(nèi)存溢出

為解決由大量圖片顯示造成的內(nèi)存溢出,可以使用BitmapFactory.Options類(lèi),在返回參數(shù)時(shí),只返回Bitmap的尺寸大小,而不將其加載到內(nèi)存中,可有效減少內(nèi)存溢出。同時(shí)在加載完后調(diào)用system.gc()通知系統(tǒng)及時(shí)回收。

1.2.3 從數(shù)據(jù)庫(kù)中取出大量數(shù)據(jù)造成的內(nèi)存溢出endprint

檢查在數(shù)據(jù)庫(kù)查詢(xún)中,是否有一次獲得全部數(shù)據(jù)的查詢(xún)。一般而言,如果一次取十萬(wàn)條記錄到內(nèi)存,就可能引起內(nèi)存溢出。該問(wèn)題比較隱蔽,在上線(xiàn)前,數(shù)據(jù)庫(kù)中數(shù)據(jù)較少,通常運(yùn)行正常,上線(xiàn)后,數(shù)據(jù)庫(kù)中數(shù)據(jù)增多,一次查詢(xún)即有可能引起內(nèi)存溢出。因此,對(duì)于數(shù)據(jù)庫(kù)查詢(xún),盡量采用分頁(yè)的方式查詢(xún)。

1.2.4 代碼中存在死循環(huán)或循環(huán)產(chǎn)生過(guò)多重復(fù)對(duì)象實(shí)體造成的內(nèi)存溢出

出現(xiàn)這種情況,只能通過(guò)查看日志找出產(chǎn)生該問(wèn)題的原因,檢查代碼中是否有死循環(huán)、遞歸調(diào)用,或大循環(huán)重復(fù)產(chǎn)生的新對(duì)象實(shí)體。

1.2.5 內(nèi)存分配大小不夠

虛擬機(jī)默認(rèn)的內(nèi)存大小對(duì)于大程序來(lái)說(shuō)可能根本不夠用,這時(shí)則需要手動(dòng)更改默認(rèn)的內(nèi)存大小。對(duì)于Android平臺(tái)而言,其托管層使用的Dalvik JavaVM從目前的表現(xiàn)看還有很多地方可以進(jìn)行優(yōu)化處理,比如在開(kāi)發(fā)一些大型游戲或比較消耗資源的應(yīng)用中可能考慮手動(dòng)干涉GC處理,如使用 dalvik.system.VMRuntime類(lèi)提供的setTargetHeapUtilization方法可以增強(qiáng)程序堆內(nèi)存的處理效率[9-11]。具體原理可以參考開(kāi)源工程,使用方法代碼如下:

Private final static float HEAP_UTILIZATION=0.6f;

//在程序onCreate時(shí)調(diào)用

VMRuntime.getRuntime().setTargetHeapUtilization(HEAP_UTILIZATION);

//自定義堆內(nèi)存大小,如:

Private final static int HEAP_SIZE=8*1024*1024;

//設(shè)置最小堆內(nèi)存大小為8MB

VMRuntime.getRuntime().setMininumHeapSize(HEAP_SIZE);

2 由圖片造成內(nèi)存溢出的新解決方法與特點(diǎn)

2.1 解決方法

對(duì)于Android程序而言,大量高質(zhì)量圖片的顯示幾乎無(wú)法避免,這也是造成內(nèi)存溢出最常見(jiàn)的原因之一。常見(jiàn)的解決方法是由程序員考慮到每一個(gè)可能造成內(nèi)存溢出的情況,然后加以防范。但是若使用新組件RecyclerView,并改用RecyclerView.Adpter,則可以將由圖片造成的內(nèi)存溢出交由RecyclerView類(lèi)解決。RecyclerView類(lèi)主要關(guān)注的是資源的回收與重用。使用RecyclerView.Adpter的關(guān)鍵代碼如下:

public class SimpleAdapter extends RecyclerView.Adapter{

/**

使用RecyclerView.Adapter重點(diǎn)在于重載這兩個(gè)方法,第一個(gè)方法負(fù)責(zé)創(chuàng)建ViewHolder,第二個(gè)方法負(fù)責(zé)顯示ViewHolder。只要將ViewHolder創(chuàng)建好,剩下資源的回收和重用RecyclerView會(huì)自動(dòng)解決。

*/

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

}

public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {

}

另外,對(duì)于服務(wù)器上的圖片,Android端可以直接使用路徑訪(fǎng)問(wèn),不需要從服務(wù)器端下載到客戶(hù)端再進(jìn)行顯示。即使要緩存到Android本地,也可以直接保存路徑。

2.2 特點(diǎn)

使用該方法,不僅可以讓同一個(gè)fragment中的內(nèi)容類(lèi)型不一樣,使單個(gè)頁(yè)面的內(nèi)容多元化,最主要的是RecyclerView不關(guān)心視圖問(wèn)題,中心放在回收和重用上。由RecyclerView直接進(jìn)行資源的回收和利用,使程序員不需要再考慮是否會(huì)發(fā)生內(nèi)存溢出,節(jié)省程序員在該方面花費(fèi)的時(shí)間,提高程序編寫(xiě)效率。

3 結(jié)語(yǔ)

內(nèi)存泄漏和內(nèi)存溢出是Android開(kāi)發(fā)中最為常見(jiàn)且繁瑣的問(wèn)題之一,在實(shí)際開(kāi)發(fā)過(guò)程中想要徹底根除這兩個(gè)問(wèn)題幾乎不可能,只能在編寫(xiě)代碼時(shí)考慮全面,提前作好防范,養(yǎng)成良好的編程習(xí)慣,從而達(dá)到有效防止內(nèi)存泄露和內(nèi)存溢出的效果。通過(guò)對(duì)內(nèi)存泄漏和內(nèi)存溢出常見(jiàn)類(lèi)型和解決方法的合理總結(jié)和歸納,可有效解決Android開(kāi)發(fā)中遇到的一系列難點(diǎn)。

對(duì)內(nèi)存的管理,關(guān)鍵在于資源的及時(shí)回收以及對(duì)內(nèi)存泄漏的預(yù)防。內(nèi)存的回收主要是對(duì)圖片等其他對(duì)象的回收與利用。其中預(yù)防內(nèi)存泄漏最主要的方法是將對(duì)Activity的Context的傳入改為對(duì)Application的Context的傳入,因?yàn)樵诤芏郩I界面以及廣播等的使用過(guò)程中幾乎都需要用到Context,而如果用Activity的Context,那么幾乎整個(gè)應(yīng)用程序中都會(huì)遍布Activity的Context,從而導(dǎo)致Activity無(wú)法成功銷(xiāo)毀,最終導(dǎo)致內(nèi)存泄漏。所以在需要傳入Context時(shí),一定要謹(jǐn)慎思考其可行性。另一種預(yù)防內(nèi)存泄漏的方法是將對(duì)Activity的強(qiáng)引用改為弱引用或軟引用,使GC在回收時(shí),能成功回收該Activity所占用的內(nèi)存資源。

參考文獻(xiàn):

[1] 周志明.深入理解Java虛擬機(jī):JVM高級(jí)特性與最佳實(shí)踐[M].第2版.北京:機(jī)械工業(yè)出版社,2013:50-98.

[2] 張秀宏.自己動(dòng)手寫(xiě)Java虛擬機(jī)[M].北京:機(jī)械工業(yè)出版社,2016:60-98.

[3] 葛一鳴.實(shí)戰(zhàn)Java虛擬機(jī)—JVM故障診斷與性能優(yōu)化[M].北京:電子工業(yè)出版社,2015:30-45.

[4] 高翔龍.Java虛擬機(jī)精講[M].北京:電子工業(yè)出版社,2015:88-98.

[5] 羅彧成.Android應(yīng)用性能優(yōu)化最佳實(shí)踐[M].北京:機(jī)械工業(yè)出版社,2017:70-110.

[6] 埃爾韋.Android應(yīng)用性能優(yōu)化[M].白龍,譯.北京:人民郵電出版社,2012:10-50.

[7] DOUG SILLARS.高性能Android應(yīng)用開(kāi)發(fā)[M].王若蘭,周丹紅,譯.北京:人民郵電出版社,2016:98-119.

[8] 騰訊SNG專(zhuān)項(xiàng)測(cè)試團(tuán)隊(duì).Android移動(dòng)性能實(shí)戰(zhàn)[M].北京:電子工業(yè)出版社,2017: 50-152.

[9] 鐘世禮.深入解析Android虛擬機(jī)[M].北京:人民郵電出版社,2016:40-48.

[10] 張國(guó)印,吳艷霞. AndroidDalvik虛擬機(jī)結(jié)構(gòu)及機(jī)制剖析[M].北京:清華大學(xué)出版社,2014:1-20.

[11] 張子言.深入解析Android虛擬機(jī)[M].北京:清華大學(xué)出版社,2014:50-90.

主站蜘蛛池模板: 亚洲免费黄色网| 国产综合精品一区二区| 国产在线八区| 亚洲欧洲日韩综合色天使| 毛片在线看网站| 日本三级欧美三级| 真实国产精品vr专区| 免费久久一级欧美特大黄| 精品91自产拍在线| 欧美黄网站免费观看| 91精品伊人久久大香线蕉| 高清不卡一区二区三区香蕉| 亚洲精品视频免费| 91免费国产在线观看尤物| 日韩欧美中文在线| 丁香综合在线| 99久久国产综合精品女同| 日韩高清欧美| 国产欧美另类| 一级爱做片免费观看久久| 国产三级成人| 华人在线亚洲欧美精品| 国产激情第一页| 国产日本一线在线观看免费| 日韩天堂视频| 国产理论最新国产精品视频| 天堂网国产| 乱人伦99久久| 午夜日b视频| 狠狠色噜噜狠狠狠狠奇米777| 国产白浆在线| 国产真实乱了在线播放| 丝袜无码一区二区三区| 成年人福利视频| 亚洲一级色| 2020精品极品国产色在线观看| 国产区在线观看视频| 欧美精品v| 亚洲日产2021三区在线| 色天天综合| 国产乱人伦AV在线A| 久久无码av三级| 97青青青国产在线播放| 国产成人乱无码视频| 最新日本中文字幕| 欧美国产日韩在线播放| 久久精品aⅴ无码中文字幕| 国产成人精品日本亚洲| 国产精品网曝门免费视频| 国产一二三区在线| 久久久国产精品无码专区| 国产SUV精品一区二区| 久久一色本道亚洲| 在线亚洲精品自拍| 国产精品私拍在线爆乳| 亚洲欧美h| 日韩在线播放中文字幕| 久久精品亚洲热综合一区二区| 自慰网址在线观看| 婷婷伊人五月| 色男人的天堂久久综合| 中文字幕久久波多野结衣| 午夜啪啪网| 精品三级网站| 亚洲天堂区| 男人的天堂久久精品激情| 伊人成人在线视频| 国产日本一线在线观看免费| 狠狠色噜噜狠狠狠狠奇米777| 久久无码高潮喷水| 99热线精品大全在线观看| 激情在线网| 亚洲天堂首页| 成人国产精品网站在线看| 99青青青精品视频在线| 婷婷亚洲综合五月天在线| 美女无遮挡被啪啪到高潮免费| 国产精品亚洲欧美日韩久久| P尤物久久99国产综合精品| 丁香婷婷久久| 国产av一码二码三码无码| 久久久久人妻一区精品色奶水 |