亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

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

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

        何群芳+時招軍

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

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

        DOIDOI:10.11907/rjdk.172379

        中圖分類號:TP301

        文獻標(biāo)識碼:A 文章編號:1672-7800(2018)002-0050-03

        0 引言

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

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

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

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

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

        1.1.1 集合類泄漏

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        Private final static float HEAP_UTILIZATION=0.6f;

        //在程序onCreate時調(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)存溢出的新解決方法與特點

        2.1 解決方法

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

        public class SimpleAdapter extends RecyclerView.Adapter{

        /**

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

        */

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

        }

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

        }

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

        2.2 特點

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

        3 結(jié)語

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

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

        參考文獻:

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

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

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

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

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

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

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

        [8] 騰訊SNG專項測試團隊.Android移動性能實戰(zhàn)[M].北京:電子工業(yè)出版社,2017: 50-152.

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

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

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

        中文字幕亚洲视频一区| 欧美成人在线A免费观看| 一区二区视频观看在线| 高清亚洲成av人片乱码色午夜| 各类熟女熟妇激情自拍| 久久成人成狠狠爱综合网| 人妻丝袜av中文系列先锋影音| 草草网站影院白丝内射| 国产精品日韩中文字幕| 日韩五码一区二区三区地址| 亚洲乱码无人区卡1卡2卡3| 337p西西人体大胆瓣开下部| 图图国产亚洲综合网站| 亚洲乱码中文字幕综合| 丝袜美腿人妻第一版主| 天堂中文а√在线| a级毛片内射免费视频| 探花国产精品三级在线播放 | 45岁妇女草逼视频播放| 国产精品特级毛片一区二区三区| 久久日本三级韩国三级| 91精品国产无码在线观看| 久久精品国产9久久综合| 国产亚洲精品美女久久久m| 婷婷色中文字幕综合在线| 69天堂国产在线精品观看| 女人天堂av免费在线| 日韩欧美中文字幕公布| 国产成人综合久久亚洲精品| 亚洲一区二区久久青草| 亚洲国产综合精品一区| 内射中出日韩无国产剧情| 天堂8中文在线最新版在线| 欧美激情精品久久999| 国产精品髙潮呻吟久久av| 精品福利一区二区三区免费视频| 精品久久久噜噜噜久久久| 久天啪天天久久99久孕妇| 亚州无吗一区二区三区| 成人免费a级毛片| 国产成人啪精品午夜网站|