日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Android內存泄漏思考

瀏覽:20日期:2022-09-27 10:43:52

Android內存泄漏是一個經常要遇到的問題,程序在內存泄漏的時候很容易導致OOM的發生。那么如何查找內存泄漏和避免內存泄漏就是需要知曉的一個問題,首先我們需要知道一些基礎知識。

Java的四種引用

強引用: 強引用是Java中最普通的引用,隨意創建一個對象然后在其他的地方引用一下,就是強引用,強引用的對象Java寧愿OOM也不會回收他

軟引用: 軟引用是比強引用弱的引用,在Java gc的時候,如果軟引用所引用的對象被回收,首次gc失敗的話會繼而回收軟引用的對象,軟引用適合做緩存處理 可以和引用隊列(ReferenceQueue)一起使用,當對象被回收之后保存他的軟引用會放入引用隊列

弱引用: 弱引用是比軟引用更加弱的引用,當Java執行gc的時候,如果弱引用所引用的對象被回收,無論他有沒有用都會回收掉弱引用的對象,不過gc是一個比較低優先級的線程,不會那么及時的回收掉你的對象。 可以和引用隊列一起使用,當對象被回收之后保存他的弱引用會放入引用隊列

虛引用: 虛引用和沒有引用是一樣的,他必須和引用隊列一起使用,當Java回收一個對象的時候,如果發現他有虛引用,會在回收對象之前將他的虛引用加入到與之關聯的引用隊列中。 可以通過這個特性在一個對象被回收之前采取措施

下面是一個例子:

public class Main { public static void main(String[] args) throws InterruptedException {ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();String sw = '虛引用';switch (sw) { case '軟引用':Object objSoft = new Object();SoftReference<Object> softReference = new SoftReference<>(objSoft, referenceQueue);System.out.println('GC前獲取:' + softReference.get());objSoft = null;System.gc();Thread.sleep(1000);System.out.println('GC后獲取:' + softReference.get());System.out.println('隊列中的結果:' + referenceQueue.poll());break;/* * GC前獲取:java.lang.Object@61bbe9ba * GC后獲取:java.lang.Object@61bbe9ba * 隊列中的結果:null * */ case '弱引用':Object objWeak = new Object();WeakReference<Object> weakReference = new WeakReference<>(objWeak, referenceQueue);System.out.println('GC前獲取:' + weakReference.get());objWeak = null;System.gc();Thread.sleep(1000);System.out.println('GC后獲取:' + weakReference.get());System.out.println('隊列中的結果:' + referenceQueue.poll());/** GC前獲取:java.lang.Object@61bbe9ba* GC后獲取:null* 隊列中的結果:java.lang.ref.WeakReference@610455d6* */break; case '虛引用':Object objPhan = new Object();PhantomReference<Object> phantomReference = new PhantomReference<>(objPhan, referenceQueue);System.out.println('GC前獲取:' + phantomReference.get());objPhan = null;System.gc();//此處的區別是當objPhan的內存被gc回收之前虛引用就會被加入到ReferenceQueue隊列中,其他的引用都為當引用被gc掉時候,引用會加入到ReferenceQueue中Thread.sleep(1000);System.out.println('GC后獲取:' + phantomReference.get());System.out.println('隊列中的結果:' + referenceQueue.poll());/** GC前獲取:java.lang.Object@61bbe9ba* GC后獲取:null* 隊列中的結果:java.lang.ref.WeakReference@610455d6* */break;} }} Java GC

目前oracle jdk和open jdk的虛擬機都為Hotspot,android 為Dalvik和Art

曾經的GC算法:引用計數

簡短的說引用計數就是對每一個對象的引用計算數字,如果引用就+1,不引用就-1,回收掉引用計數為0的對象。來達到垃圾回收

弊端:如果兩個對象都應該被回收但是他倆卻互相依賴,那么他兩者的引用永遠都不會為0,那么就永遠無法回收, 無法解決循環引用的問題

這個算法只在很少數的虛擬機中使用過

現代的GC算法

標記回收算法(Mark and Sweep GC) :從'GC Roots'集合開始,將內存整個遍歷一次,保留所有可以被GC Roots直接或間接引用到的對象,而剩下的對象都當作垃圾對待并回收,這個算法需要中斷進程內其它組件的執行并且可能產生內存碎片。 復制算法(Copying) :將現有的內存空間分為兩快,每次只使用其中一塊,在垃圾回收時將正在使用的內存中的存活對象復制到未被使用的內存塊中,之后,清除正在使用的內存塊中的所有對象,交換兩個內存的角色,完成垃圾回收。 標記-壓縮算法(Mark-Compact) :先需要從根節點開始對所有可達對象做一次標記,但之后,它并不簡單地清理未標記的對象,而是將所有的存活對象壓縮到內存的一端。之后,清理邊界外所有的空間。這種方法既避免了碎片的產生,又不需要兩塊相同的內存空間,因此,其性價比比較高。 分代 :將所有的新建對象都放入稱為年輕代的內存區域,年輕代的特點是對象會很快回收,因此,在年輕代就選擇效率較高的復制算法。當一個對象經過幾次回收后依然存活,對象就會被放入稱為老生代的內存空間。對于新生代適用于復制算法,而對于老年代則采取標記-壓縮算法。

以上四種算法信息引用自QQ空間團隊分享 Android GC 那點事 &version=11000003&pass_ticket=nhSGhYD4LC9FWvUPv26Y7AdIzqEDu8FTImf2AKlyrCk%3D) ,總結的特別棒

導致內存泄漏的原因

對象在GC Root中可達,也就是他的引用不為空,所以GC無法回收它也就會導致內存泄漏

GC Root起點

虛擬機棧中引用的對象 方法區中類靜態屬性引用的對象 方法區中常量引用的對象 JNI引用的對象 GC可以續一秒

當一個對象在引用鏈中失S#x53BB;了引用,那么他就真的要告別世界了嗎,其實并不是,虛擬機會給他“緩刑”,每一個對象有一個finalize() 方法,虛擬機是否給他緩刑取決于這個對象的這個方法是否被執行,如果這個對象的這個方法沒有被覆蓋或者這個方法被執行過一次,那么就要“行刑”了。真的是“續一秒”

如果這個對象的finalize()方法應該被執行,那么虛擬機會將它放在F-Queue隊列中,稍后虛擬機會自動創建一個Finalizer線程去執行這個隊列中的對象的這個方法。如果對象在finalize()中成功自救,舉個例子,把自己和一個存在的對象強引用,那么就不會被回收,否則就真的被回收了。

但是虛擬機并不會保證Finalizer線程執行結束再進行回收,因為如果在某一個對象的finalize()方法中執行了死循環或者超級耗時的操作,虛擬機等待這個執行結束的話就會導致整個Gc崩潰了

首先注意這個方法只能被執行一次,第二次就會標記了這個方法被執行過不會再執行了,其次,這個方法不一定會被執行到,所以不要依賴finalize()去自救。這不是好的做法。

并發GC和非并發GC

Android2.3之后支持了并發的GC。

非并發GC : 虛擬機在執行GC的時候進行Stop the world,也就是掛起其他所有的線程,通常會持續上百毫秒,一次Mark,然后直接清理

Android內存泄漏思考

并發GC : 跟非并發的簡單gc來比較,一般非并發GC需要耗費上百ms的時間來進行,而并發gc僅僅需要10ms左右的時間,效率大幅度提升(數據來自:技術小黑屋大大),但是并發gc由于需要進行重復的處理改動的對象,所以需要更多的CPU資源

Android內存泄漏思考

兩者的差別:

首先非并發GC簡單粗暴,直接掛起所有的線程,此時Java堆中肯定不會有任何的添加和修改,此時去遞歸GC樹,然后標記-清理。但是這樣會造成很大的開銷,大家都等著你豈不是很沒面子= =

然而非并發的GC是一點一點來的,跟線程同步進行這樣就不會有很長時間的等待,但是你要明白一個道理,想把地掃干凈這段時間必須沒人來踩,所以他要有掛起線程的過程。

那么并發是怎么實現的呢?首先有個知識點就是Jvm在分配內存的時候,有兩種方式

指針碰撞:一個指針,申請一塊內存就指針挪動相應的距離,不會產生內存碎片,這要求內存是很規整的 空閑列表:每次申請一塊內存給需要的對象,然后有一個列表記錄了哪些位置被申請了,下次申請的時候就不申請這個位置,這樣適用于內存不是很規整的情況

創建對象是一個頻繁的操作,那么我們如何保證原子性呢?兩種方案

CAS(Compare and Swap)策略配上失敗重試來保證原子性 每個線程分配一個TLAB : 很簡單,每個線程自己有自己的一塊內存,那么分配的時候自己鎖自己的分區就行了,提高了效率

我們用的是第二種 233

所以獲取Java堆鎖的時候,重點來了,我們逐個線程去鎖TLAB,而不是一次全鎖住,當然提高了并發GC的效率,所以更快。但是引來的問題就是并發的問題,所以下一步要重復去修改在一個個探索時候被改的對象。也就需要更多的CPU資源。

我們為什么要關注GC

首先我們知道虛擬機如何去GC才能了解到如何讓一個對象被正確的回收,這樣才不能內存泄漏

其次無論是并發GC還是非并發GC都會導致掛起其他的所有線程,那么就會帶來程序卡頓。

ART在GC上做到了更加細粒度的控制,可以更加流暢的GC

常見的內存泄漏案例:Handler內存泄漏

首先鋪墊一句話:非靜態的內部類和匿名類會隱式的持有外部類的引用

public class MainActivity extends AppCompatActivity { private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) { Log.d('smallSohoSolo', 'Hello Handler');} }; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mHandler.postDelayed(new Runnable() { @Override public void run() {Log.d('smallSohoSolo', 'Running'); }}, 1000 * 60 * 10); //10分鐘之后執行finish(); }}

這段代碼有很明顯的內存泄漏,首先Handler和Runnable都是匿名內部類的實例,他們都會持有MainActivity的引用,

Handler發送的消息到了消息隊列中 Activity被結束掉 這個消息中包含了Handler的引用,Handler包含了Activity的引用,而且他還是個Runnable,也是匿名內部類,也間接包含了MainActivity引用 在Main Lopper中,當此消息被取出來,這未執行的10分鐘里面,MainActivity沒法回收 內存泄漏

有人可能會說短暫的內存泄漏又能怎樣?這是錯誤的想法,因為只要發生內存泄漏,在這段時間只要進行了大內存的操作(比如加載一個照片墻),就有風險因為這個內存泄漏造成OOM(占用內存肯定剩下的少了)

上面這個如何修改呢?

將Runnable和Handler改成static 或者在外部定義內部使用。

其他常見的內存泄漏 靜態變量內存泄漏:使用靜態變量來引用一個事物,在不使用之后沒有下掉,那么引用存在就會一直泄漏 單例導致的內存泄漏:使用的單例中保存了不應該被一直持有的對象,那么就會造成內存泄漏 由第三方庫使用不當導致的內存泄漏:比如EventBus,Activity銷毀的時候沒有反注冊就會導致引用一直被持有無法回收 還有很多。。。他們都是因為引用沒有被清理造成的 如何查看內存泄漏

簡單粗暴 —> LeakCanary: Square出品的庫,當出現內存泄漏的時候會出現

精打細算 —> Android Studio 內存工具: 可以Dump下來當前的內存路徑,然后分析出來哪些對象目前的狀態。很強

參考文獻 深入理解Java虛擬機 Form: 周志明 Android GC那點事 &version=11000003&pass_ticket=nhSGhYD4LC9FWvUPv26Y7AdIzqEDu8FTImf2AKlyrCk%3D) Form: QQ空間終端團隊 細話Java:'失效'的private修飾符 Form: 技術小黑屋 避免Android中Context引起的內存泄露 Form: 技術小黑屋 Handler引起的內存泄漏 Form: 技術小黑屋 Android 內存泄漏案例和解析 Form: drakeet

來自:https://techblog.toutiao.com/2017/08/16/untitled-4/

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
蜜臀精品一区二区三区在线观看| 精品免费av一区二区三区| 国产情侣久久| 亚洲一区国产| 成人免费电影网址| 在线天堂资源www在线污| 九九99久久精品在免费线bt| 国产欧美丝祙| 97精品国产福利一区二区三区| 国产91欧美| 欧洲av不卡| 国精品一区二区三区| 激情久久久久久久| 亚洲神马久久| 免费视频一区二区| 99国产成+人+综合+亚洲欧美| 亚洲国产专区校园欧美| 黄毛片在线观看| 欧美精选视频一区二区| 国产精品久久久久av电视剧| 欧美~级网站不卡| 五月婷婷亚洲| 久久免费高清| 亚洲激情偷拍| 日本欧美一区二区在线观看| 日韩一区二区三区在线看| 91成人福利| 国内精品亚洲| 亚洲二区三区不卡| 亚洲精品三级| 亚洲精品亚洲人成在线观看| 欧美日韩1区2区3区| 欧美精品自拍| 婷婷久久免费视频| 红桃视频国产精品| 久久国产人妖系列| 亚洲电影在线一区二区三区| 麻豆91精品视频| 午夜影院一区| 久久xxxx精品视频| 日韩有码av| 精品国产a一区二区三区v免费| 成人在线免费观看91| 亚洲特色特黄| 日本在线成人| 91欧美在线| 香蕉久久久久久久av网站| 亚洲精品欧洲| 国产精品yjizz视频网| 亚洲精品国产偷自在线观看| 欧美在线看片| 日韩精品欧美| 欧美日韩一区二区国产| 久久久久久久久丰满| 亚洲精品无播放器在线播放| 国产成人精品福利| 视频一区视频二区中文| 九九久久国产| 亚洲一区亚洲| 国产a亚洲精品| 日韩精品一卡二卡三卡四卡无卡| 久久精品福利| 制服诱惑一区二区| 国产在线一区不卡| 亚洲精品少妇| 99久久亚洲精品蜜臀| 国产日韩欧美一区二区三区 | 少妇精品导航| 日本aⅴ免费视频一区二区三区| 日韩精品免费一区二区三区| 蜜桃免费网站一区二区三区| 热久久国产精品| 69精品国产久热在线观看| 香蕉国产精品| 欧美中文一区二区| 国产一区二区三区四区五区| 岛国av在线网站| 丝袜国产日韩另类美女| 国产日韩1区| 久久精品国产网站| 欧美亚洲tv| 欧美va天堂在线| 麻豆国产欧美日韩综合精品二区| 国产精品毛片一区二区三区| 精品国产aⅴ| 91免费精品国偷自产在线在线| 在线精品视频在线观看高清| 国产精品丝袜在线播放| 视频精品一区二区| 日韩视频一区二区三区在线播放免费观看| 老司机久久99久久精品播放免费| 国产精品第一国产精品| 久久男人av资源站| 日韩另类视频| 在线日韩av| 欧美日韩亚洲一区在线观看| 91精品久久久久久久久久不卡| 欧美午夜网站| 国产色99精品9i| 午夜一级在线看亚洲| 久久gogo国模啪啪裸体| 亚洲精品在线观看91| 亚洲精品美女91| 亚洲综合图色| 日韩欧美午夜| av亚洲一区二区三区| 欧美另类中文字幕 | 精品视频高潮| 日韩久久一区| 亚洲精品大全| 欧美日一区二区在线观看| 久久免费精品| 最新中文字幕在线播放| 成人日韩在线| 国产精品日本一区二区不卡视频| 欧美日韩免费观看一区=区三区 | 蜜桃视频免费观看一区| 丝袜美腿亚洲一区| 精品国产中文字幕第一页| av在线日韩| 在线亚洲观看| 亚洲高清激情| 国产综合色产| 91亚洲精品视频在线观看| 精品亚洲二区| 精品99在线| 日本在线高清| 精品1区2区3区4区| 丝袜美腿成人在线| 亚洲aⅴ网站| 日韩专区一卡二卡| 日韩有吗在线观看| 精品国产一区二区三区性色av| 麻豆国产精品777777在线| 日韩精品一二三四| 精品捆绑调教一区二区三区| 久久国产中文字幕| 亚洲一区观看| 久久精品72免费观看| 国产精品sss在线观看av| 欧美黄色一区| 久久婷婷丁香| 婷婷激情一区| 欧洲精品一区二区三区| 人在线成免费视频| 久久蜜桃精品| 亚洲欧洲一区| 亚洲精品字幕| 国产精品亲子伦av一区二区三区 | 鲁大师精品99久久久| 久久久久久色 | 国产精品对白久久久久粗| 精品亚洲二区| 国产99久久久国产精品成人免费| 鲁大师影院一区二区三区| 日本不卡视频在线观看| 精品资源在线| 欧美日韩一二| 亚洲一区黄色| 欧美精品影院| 精品国产aⅴ| 丝袜av一区| 99国产成+人+综合+亚洲欧美| 亚洲精品黄色| 久久免费精品| 麻豆mv在线观看| 香蕉久久99| 日韩精彩视频在线观看| 久久精品国产精品亚洲毛片| 久久国产亚洲精品| 免费看欧美美女黄的网站| 国产精品任我爽爆在线播放 | 蜜桃视频一区二区| 美女国产精品久久久| 久久国产日本精品| 99re国产精品| 中文字幕乱码亚洲无线精品一区| 日韩视频一区| 香蕉国产精品| 99视频精品全国免费| 国产专区精品| 欧美一级网站| 日韩欧美国产精品综合嫩v| 久热re这里精品视频在线6| 国产欧美日韩在线一区二区| 久久男女视频| 亚洲五月综合| 欧美日韩国产传媒| 福利片在线一区二区| 日韩动漫一区| 播放一区二区| 色爱av综合网| 久久精品日韩欧美| 成人午夜在线| 黄色在线网站噜噜噜| 国产精品一区二区三区美女| 欧美日韩精品一区二区三区在线观看| 久久夜色精品| 欧美激情视频一区二区三区免费 | 欧美国产偷国产精品三区|