大香蕉综合在线观看视频-日本在线观看免费福利-欧美激情一级欧美精品性-综合激情丁香久久狠狠

好房網(wǎng)

網(wǎng)站首頁 行業(yè)快訊 > 正文

今日更新安卓怎么清理內(nèi)存(Android優(yōu)化———內(nèi)存優(yōu)化)

2022-05-20 08:08:33 行業(yè)快訊 來源:
導讀 目前大家應該是對安卓怎么清理內(nèi)存(Android優(yōu)化———內(nèi)存優(yōu)化)比較感興趣的,所以今天好房網(wǎng)小編CC就來為大家整理了一些關(guān)于安卓怎么清
目前大家應該是對安卓怎么清理內(nèi)存(Android優(yōu)化———內(nèi)存優(yōu)化)比較感興趣的,所以今天好房網(wǎng)小編CC就來為大家整理了一些關(guān)于安卓怎么清理內(nèi)存(Android優(yōu)化———內(nèi)存優(yōu)化)方面的相關(guān)知識來分享給大家,希望大家會喜歡哦。

安卓怎么清理內(nèi)存(Android優(yōu)化———內(nèi)存優(yōu)化)

Java虛擬機Java內(nèi)存模型

Android優(yōu)化———內(nèi)存優(yōu)化

虛擬機棧(線程私有):局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息

堆(線程共享):實例對象

方法區(qū)(線程共享):類信息,常量,即時編譯器編譯后的代碼

程序計數(shù)器(線程私有):字節(jié)碼行號指示器,記錄當前線程執(zhí)行到多少行

本地方法棧(線程私有):和虛擬機棧類似,兩者的區(qū)別就是虛擬機棧是為虛擬機執(zhí)行java方法服務,本地方法棧為虛擬機執(zhí)行native方法服務 。

程序計數(shù)器

線程計數(shù)器中如果正在執(zhí)行java方法,計數(shù)器記錄的是當前指令的地址,

如果是Native方法,計數(shù)器記錄為空

堆內(nèi)存 = 新生代(1) + 老年代(2)

新生代:復制算法

老年代:標記整理算法

方法區(qū)

也叫“永久代”,8以后將方法區(qū)去除了,將方法區(qū)移動到直接內(nèi)存

內(nèi)存回收主要考慮堆區(qū)和方法區(qū)的回收,其他部分會根據(jù)線程的產(chǎn)生和消亡

個版本區(qū)別

Android優(yōu)化———內(nèi)存優(yōu)化

Android優(yōu)化———內(nèi)存優(yōu)化

Android優(yōu)化———內(nèi)存優(yōu)化

6:運行常量池在方法區(qū)

7:運行常量池在堆中

8:刪除方法區(qū),引入直接內(nèi)存,元空間概念,方法區(qū)中的靜態(tài)變量被轉(zhuǎn)移到堆中,只有class元數(shù)據(jù)在元空間。

堆中的老年代和方法區(qū)(永久代)是綁定的,無論哪一方滿了,都會觸發(fā)雙方的GC回收

問題:

堆和棧的區(qū)別:棧:基本數(shù)據(jù)類型變量(int、short、long、byte、float、double、boolean、char)以及對象的引用變量堆:存儲java對象堆中的對象對所有線程可見,棧內(nèi)存只屬于一個線程堆的內(nèi)存空間遠遠大于棧

為什么刪除方法區(qū)?啟動大小固定,很難調(diào)優(yōu),容易發(fā)生OOM元空間在本地內(nèi)存中分配,本地內(nèi)存足夠就不會溢出

GC垃圾回收判斷對象是否存活

引用計數(shù)算法(缺點:循環(huán)引用,技數(shù)永遠不為0)

可達性算法(二叉樹中向下搜索,不存在引用鏈則對象不可用)

回收算法

標記清除算法:標記完后對對象進行回收,使用在老年代缺點:效率不高,標記和清除效率不高差生大量碎片空間,導致空間浪費

復制算法:將可用對象復制到新的連續(xù)空間,刪除之前的空間缺點:浪費50%的內(nèi)存,復制長生存期的對象效率低下,所以該算法使用在新生代

標記整理算法:前期使用標記清除算法,后續(xù)使用整理算法,使對象排列稱聯(lián)系空間,使用在老年代

分代收集算法:對數(shù)據(jù)進行分代,每一代執(zhí)行不同的回收算法

年輕代分為eden、s0、s1區(qū),分別為8:1:1,年輕代和老年代為1:2

元空間的gc:元空間中的類加載器存活,則元空間中元數(shù)據(jù)也存活

Minor GC : 清理年輕代

Major GC : 清理老年代

Full GC : 清理整個堆空間,包括年輕代和永久代

四大引用介紹簡述

強引用:Strong Reference,通常使用的對象方式,gc不會回收

軟引用:SoftReference,當內(nèi)存不足時進行回收

弱引用:WeakReference,下一次gc時回收

虛引用:PhantomReference,任何時候可回收

在內(nèi)存泄露問題處理上,使用最多的是弱引用,許多源碼、框架都是用

eg:

ThreadLocalMap中存儲以ThreadLocal的弱引用為鍵,具體內(nèi)容為value

Glide中緩存使用activeResource,存儲的是圖片的弱引用

解決Handler的內(nèi)存泄漏使用弱引用

Reference理解

所有的引用都是繼承自Reference,以下以WeakReference為例:

publicclassWeakReference<T>extendsReference<T>{/***Createsanewweakreferencethatreferstothegivenobject.Thenew*referenceisnotregisteredwithanyqueue.**@paramreferentobjectthenewweakreferencewillreferto*/publicWeakReference(Treferent){super(referent);}/***Createsanewweakreferencethatreferstothegivenobjectandis*registeredwiththegivenqueue.**@paramreferentobjectthenewweakreferencewillreferto*@paramqthequeuewithwhichthereferenceistoberegistered,*or<tt>null</tt>ifregistrationisnotrequired*/publicWeakReference(Treferent,ReferenceQueue<?superT>q){super(referent,q);}}

其中存在兩種構(gòu)造方法,區(qū)別在于是否傳入引用隊列,如果不傳入引用隊列,說明只存在一種引用,不需要引用隊列成鏈存儲

publicabstractclassReference<T>{privatestaticbooleandisableIntrinsic=false;privatestaticbooleanslowPathEnabled=false;//引用的對象,由垃圾回收器控制其引用volatileTreferent;/*TreatedspeciallybyGC*/finalReferenceQueue<?superT>queue;ReferencequeueNext;Reference<?>pendingNext;publicTget(){returngetReferent();}@FastNativeprivatefinalnativeTgetReferent();publicvoidclear(){clearReferent();}@FastNativenativevoidclearReferent();publicbooleanisEnqueued(){//Contrarytowhatthedocumentationsays,thismethodreturnsfalse//afterthisreferenceobjecthasbeenremovedfromitsqueue//(b/26647823).ReferenceQueue.isEnqueuedpreservesthishistorically//incorrectbehavior.returnqueue!=null&&queue.isEnqueued(this);}publicbooleanenqueue(){returnqueue!=null&&queue.enqueue(this);}/*--Constructors--*/Reference(Treferent){this(referent,null);}Reference(Treferent,ReferenceQueue<?superT>queue){this.referent=referent;this.queue=queue;}}

抽象類很簡短,可以看出一個關(guān)鍵點,Reference是一個節(jié)點,保存next的引用,方法調(diào)用都是使用ReferenceQueue方法,直接進入:

privateReference<?extendsT>head=null;privateReference<?extendsT>tail=null;booleanenqueue(Reference<?extendsT>reference){synchronized(lock){if(enqueueLocked(reference)){lock.notifyAll();returntrue;}returnfalse;}}privatebooleanenqueueLocked(Reference<?extendsT>r){...if(rinstanceofCleaner){Cleanercl=(sun.misc.Cleaner)r;cl.clean();r.queueNext=sQueueNextUnenqueued;returntrue;}if(tail==null){head=r;}else{tail.queueNext=r;}tail=r;tail.queueNext=r;returntrue;}

入隊方法中,

使用synchronized添加鎖,入隊結(jié)束后釋放鎖,在ReferenceQueue中并不是標準的隊列,使用的是Reference節(jié)點成鏈,行成單鏈表,類似于MessageQueue.

如果是Cleaner類,創(chuàng)建一個虛引用節(jié)點,即不如隊。Cleaner是用來釋放非堆內(nèi)存,所以做特殊處理

SoftReference

>publicclassSoftReference<T>extendsReference<T>{//時間戳,由gc更新staticprivatelongclock;privatelongtimestamp;publicSoftReference(Treferent){super(referent);this.timestamp=clock;}/***Createsanewsoftreferencethatreferstothegivenobjectandis*registeredwiththegivenqueue.**@paramreferentobjectthenewsoftreferencewillreferto*@paramqthequeuewithwhichthereferenceistoberegistered,*or<tt>null</tt>ifregistrationisnotrequired**/publicSoftReference(Treferent,ReferenceQueue<?superT>q){super(referent,q);this.timestamp=clock;}publicTget(){To=super.get();if(o!=null&&this.timestamp!=clock)this.timestamp=clock;returno;}}

由gc管理時間戳

clock:上一次gc時間

timestamp:訪問get時最近一次的gc時間

回收條件為:clock - timestamp <= free_heap * ms_per_mb

free_heep為堆空間空閑大小

ms_per_mb是保留軟引用時間/MB

PhantomReference

publicclassPhantomReference<T>extendsReference<T>{publicTget(){returnnull;}publicPhantomReference(Treferent,ReferenceQueue<?superT>q){super(referent,q);}}

虛引用的get方法返回null,不做gc保留

虛引用通過構(gòu)造方法可以查看是持有對象引用的

總結(jié):所有引用都是繼承自Reference基類的,該類是一個鏈表節(jié)點,ReferenceQueue通過這點形成單鏈表,稱之為隊列,進行引用管理,所有引用都可以通過Reference的isEnqueue方法判斷引用是否存在。

FinalizerReference理解

java堆中創(chuàng)建對象時,如果java類定義了finalize方法,就會新建一個FinalizerReference類,指向這個新建的對象

內(nèi)存問題

內(nèi)存泄漏:內(nèi)存沒有按照預期在gc時回收

內(nèi)存溢出:內(nèi)存大小超出指定大小,導致OOM

內(nèi)存抖動:短時間創(chuàng)建大量內(nèi)存對象,然后回收,導致內(nèi)存發(fā)生鋸齒形抖動,內(nèi)存空間不連續(xù)加上碎片會導致更大的空間,最終OOM

內(nèi)存優(yōu)化意義

減少OOM,提高系統(tǒng)穩(wěn)定性

減少卡頓,提高流暢度

減少內(nèi)存占用,提高應用存活率

減少異常發(fā)生和代碼邏輯隱患

Android內(nèi)存泄漏常見內(nèi)存泄漏

匿名內(nèi)部類持有外部類引用,導致外部類內(nèi)存泄漏(Handler)

單例傳入Context導致調(diào)用單例方無法被回收。

非靜態(tài)內(nèi)部類創(chuàng)建靜態(tài)實例

注冊與反注冊

資源對象關(guān)閉

集和及時清理

內(nèi)存泄漏檢測

Profiler,Memory Analyzer(MAT)

Android studio自帶內(nèi)存、cpu、網(wǎng)絡的變化,可以根據(jù)內(nèi)存變化做具體分析

LeakCanary

框架集成,自動檢測內(nèi)存泄漏,生成app,提供內(nèi)存泄漏棧堆情況

原理:綁定生命周期,對Activity和Fragment來說,在onDestory時將對象放入弱引用隊列進行存儲,觸發(fā)gc后,如果還存在,則發(fā)生內(nèi)存泄漏

StrictMode(很少用)

一款比較老的工具,ThreadPolicy可以檢測主線程是否網(wǎng)絡訪問,是否讀寫。VMPolicy檢測內(nèi)存,Activity,F(xiàn)ragment是否泄漏,資源是否正確關(guān)閉

內(nèi)存優(yōu)化空間

不必要的自動裝箱

自動裝箱就是將基礎(chǔ)數(shù)據(jù)類型轉(zhuǎn)化為對應的復雜類型,在HashMap的增刪改查中充滿了自動裝箱問題,所以盡量避免這中問題,如將HashMap替換為SparseArray和ArrayMap

內(nèi)存復用

資源復用:通用字符串,顏色,布局

視圖復用:類似于RecyclerView的優(yōu)化復用

對象池:創(chuàng)建對象池,不用重復創(chuàng)建對象,類似于線程池,messae享元模式

Bitmap對象復用:使用inBitmap屬性可以告知Bitmap解碼器嘗試使用已經(jīng)存在的內(nèi)存區(qū)域,新解碼的bitmap會嘗試使用之前那張bitmap在heap中占據(jù)的pixel data內(nèi)存區(qū)域。

在App可用內(nèi)存過低時主動釋放內(nèi)存在App退到后臺內(nèi)存緊張即將被Kill掉時選擇重寫Application中 onTrimMemory/onLowMemory 方法去釋放掉圖片緩存、靜態(tài)緩存來自保。

其他場景優(yōu)化item被回收不可見時釋放掉對圖片的引用ListView:因此每次item被回收后再次利用都會重新綁定數(shù)據(jù),只需在ImageView onDetachFromWindow的時候釋放掉圖片引用即可。RecyclerView:因為被回收不可見時第一選擇是放進mCacheView中,這里item被復用并不會只需bindViewHolder來重新綁定數(shù)據(jù),只有被回收進mRecyclePool中后拿出來復用才會重新綁定數(shù)據(jù),因此重寫Recycler.Adapter中的onViewRecycled()方法來使item被回收進RecyclePool的時候去釋放圖片引用。如果使用字符串拼接,盡量使用StringBuilder、StringBuffer(內(nèi)存抖動)自定義view減少onDraw的耗時和執(zhí)行次數(shù)盡量使用靜態(tài)內(nèi)部類盡量使用基礎(chǔ)數(shù)據(jù)類型合適的時候使用軟/弱引用

線上監(jiān)控方案

常規(guī)監(jiān)測當內(nèi)存使用超過80%,使用Debug.dumpHprofData(String fileName)

獲取dump文件回傳至服務器,而后手動分析LeakCanary集成并帶到線上

Probe線上監(jiān)測工具

LeakInspector

ResourceCanary

最后

小編在網(wǎng)上收集了一些Android 開發(fā)相關(guān)的學習文檔、面試題、Android 核心筆記等等文檔,希望能幫助到大家學習提升,如有需要參考的可以直接私信我領(lǐng)取哦

Android優(yōu)化———內(nèi)存優(yōu)化


版權(quán)說明: 本文由用戶上傳,如有侵權(quán)請聯(lián)系刪除!


標簽: