當前位置:首頁 » 安卓系統 » android軟引用

android軟引用

發布時間: 2023-05-19 01:42:03

❶ 獲取當前Activity的幾種方式

1. 通過RunningTaskInfo的topActivity獲取當前Activity實例。通過該種方式獲取的Activity,只能保證其已經執行了Activity.onCreate方法,不能保證是否執行了Activity.onResume方法。該方法在api 21以後已經被禁,使用需謹慎。

2. 通過Android 4.0之後提供的ActivityLifecycleCallbacks介面監聽當前的Activity實例,可以在onActivityCreated或者onActivityResumed當中獲取到。建議在onActivityResumed當中去獲取,同時最好以軟引用或者弱引用的方式持有,防止OOM。(其中XxxApplication是你的工程Application)

3. 手寫Activity管理棧,可以使用Stack或者List等存儲純純裂做閉已經執行了Activity.onCreate或者Activity.onResume方法的Activity,並相應在Activity.onPause或者Activity.onDestroy中移除。褲鉛

4. 反射方式

❷ android緩存硬引用和軟引用是什麼意思

強引用 SrongReference:
一般我們常用到的引用就是強引用,比如上面提到的引用計數法裡面的引用。
軟引用 SoftReference:
對於GC來說, SoftReference的強度明顯低差豎譽虛段於 SrongReference。 SoftReference修飾的引用,其告訴GC:我是一個 軟引用,當內存不足的時候,我指向的這個內存是可以給你釋放掉的。我們來看一下android系統中的一個使用實列(纖尺MessageItem.java):

❸ Glide圖片載入的用法介紹和三級緩存實現

Glide庫是用來實現圖片載入的框架,功能強大且易使用,深受大家喜愛。

為啥要做緩存? android默認給每個應用只分配16M的內存,所以如果載入過多的圖片,為了 防止內存溢出 ,應該將圖片緩存起來。

圖片的三級緩存分別是:

1、內存緩存
2、本地緩存
3、網路緩存
其中,內存緩存應優先載入,它速度最快;本地緩存次優先載入,它速度也快;網路緩存不應該優先載入,它走網路,速度慢且耗流量。

最優-優先順序:內存緩存 > 本地緩存 > 網路緩存

兩個方法實現:根據圖片的url去載入圖片、在本地和內存中緩存

兩個方法實現:設置本地緩存,以及獲取本地緩存

兩個方法實現:設置內存緩存,獲取內存緩存。

如果使用hashmap去存儲圖片時,當圖片越來越多,那麼會造成內存溢出,因為是強引用(對於強引用的系統不會回收)

如果改成軟引用softReference,在android 2.3 以上的系統,對象會被提前回收。

可以用LruCache來解決上述內存不回收或提前回收的問題。least recentlly use 最少最近使用演算法 它會將內存控制在一定的大小內, 超出最大值時會自動回收, 這個最大值開發者自己定。(這個東西沒有用過..)

參考鏈接: https://blog.csdn.net/sinat_20645961/article/details/46325243

❹ 安卓開發中提高安卓程序效率的15小技巧

安卓開發中提高安卓程序效率的15小技巧

對於一個安卓開發者來說,安卓開發中的提高安卓程序效率也是一項重要的內容,到底如何提高安卓程序效率,如何優化安卓的性能呢?以下達內南寧安卓培訓部老師介紹了15種優化安卓的性能的小技巧,希望對廣大的安卓開發者有所幫助!

1.http用gzip壓縮,設置連接超時時間和響應超時時間

http請求按照業務需求,分為是否可以緩存和不可緩存,那麼在無網路的環境中,仍然通過緩存的瀏覽部分數據,實現離線閱讀。

2.使用線程池,分為核心線程池和普通線程池,下載圖片等耗時任務放襪沖置在普通線程池,避免耗時任務阻塞線程池後,導致所有非同步任務都必須等待

3.盡量避免static成員變數引用資源耗費過多的實例,比如Context

4.listview性能優化

1).非同步載入圖片

item中如果包含有webimage,那麼最好非同步載入

2).快速滑動時不顯示圖片

當快速滑動列表時(SCROLL_STATE_FLING),item中的圖片或獲取需要消耗資源的view,可以不顯示出來;而處於其他兩種狀態(SCROLL_STATE_IDLE和SCROLL_STATE_TOUCH_SCROLL),則將那些view顯示出來

3).復用convertView

在getItemView中,判斷convertView是否為空,如果不為空,可復用。如果couvertview中的view需要添加listerner,代碼一定要在if(convertView==null){}之外告賀。

4).BaseAdapter避免內存溢出

如果BaseAdapter的實體類有屬性非常消耗內存,可以將保存到文件;為提高性能,可以進行緩存,並限制緩存大小。

5.對於一個安卓開發者來說,安卓開發中的提高安卓程序效率也是一項重要的內容,到底如何提高安卓程序效率,如何優化安卓的性能呢?以下本文就介紹了15種優化安卓的性能的小技巧,希望對廣大的安卓開發者有所幫助!

6.保證Cursor佔用的內存被及時的釋放掉,而不是等待GC來處理。並且Android明顯是傾向於編程者手動的將Cursorclose掉;

7.非同步任務,分為核心任務和普通任務,只有核心任務中出現的系統級錯誤才會報錯,非同步任務的ui操襪好派作需要判斷原activity是否處於激活狀態;

8.使用代替強引用,弱引用可以讓您保持對對象的引用,同時允許GC在必要時釋放對象,回收內存。對於那些創建便宜但耗費大量內存的對象,即希望保持該對象,又要在應用程序需要時使用,同時希望GC必要時回收時,可以考慮使用弱引用。

9.超級大胖子Bitmap及時的銷毀(Activity的onDestroy時將bitmap回收,在被UI組件使用後馬上進行回收會拋:Canvas:.graphics.Bitmap)設置一定的采樣率(有開發者提供的圖片無需進行采樣,對於有用戶上傳或第三方的大小不可控圖片,可進行采樣減少圖片所佔的內存),從服務端返回圖片,建議同時反饋圖片的size巧妙的運用軟引用drawable對應resid的資源,bitmap對應其他資源任何類型的圖片,如果獲取不到(例如文件不存在,或者讀取文件時跑OutOfMemory異常),應該有對應的默認圖片(默認圖片放在在apk中,通過resid獲取);

10.Drawable中ui組件需要用到的圖片是apk包自帶的,那麼一律用或者,而不要根據resourceid

注意:get((),R.drawable.btn_achievement_normal)該方法通過resid轉換為drawable,需要考慮回收的問題,如果drawable是對象私有對象,在對象銷毀前是肯定不會釋放內存的。

11.復用、回收Activity對象臨時的activity及時finish主界面設置為singleTask一般界面設置為singleTop。

12.在onResume時設置該界面的電源管理,在onPause時取消設置。

13.應用開發中自定義View的時候,交互部分,千萬不要寫成線程不斷刷新界面顯示,而是根據事件主動觸發界面的更新。

14.如果ImageView的圖片是來自網路,進行非同步載入。

15.位置信息獲取用戶的地理位置信息時,在需要獲取數據的時候打開GPS,之後及時關閉掉。

❺ android中四大引用的區別,強引用,軟引用,弱引用和虛引用

四大引用的區別就是內存回收的區別,強引用只要存在沒有被銷毀,內存就不會被系統回收,軟引用在內存嚴重不足的情況下會被系統回收,弱引用會在系統的內存出現報警(比嚴重不足的搏世程度基談肢低)情況下回收,虛引用很容易被回收掉。總的來說就是內存被系統回收的概率從小到大是:虛引用--弱引用--軟引侍扮用--強引用

❻ Android 【手撕Glide】--Glide緩存機制(面試)

本文源碼解析基於Glide 4.6.1

系列文章
Android 【手撕Glide】--Glide緩存機制
Android 【手撕Glide】--Glide緩存機制(面試)
Android 【手撕Glide】--Glide是如何關聯生命周期的?

Glide緩存分為內存緩存和磁碟緩存,其中內存緩存是由弱引用+LruCache組成。

取的順序是:弱引用、LruCache、磁碟
存的順序是:磁碟、弱引用、LruCache

這張親手製作的圖片,方便大家更直觀的理解緩存機制的整體流程,結合文末總結效果更佳。喜歡的記得點贊!

概述

1、弱引用是由這樣一個HashMap維護,key是緩存的key,這個key由圖片url、width、height等10來個參數組成;value是圖片資源對象的弱引用形式。

2、LruCache是由一個LinkedHashMap維護,根據Lru演算法來管理圖片。大致的原理是利用linkHashMap鏈表的特性,把最近使用過的文件插入到列表頭部,沒使用的圖片放在尾部;然後當圖片大小到達預先設置的一個閥值的時候 ,按演算法刪除列表尾部的部分數據。由於篇幅有限,這里不講解LruCache和DiskLruCache的底層原理,這里推薦一篇 圖解LinkedHashMap原理

這是Glide自定義的LruCache

存取原理
取數據
在內存緩存中有一個概念叫圖片引用計數器 ,具體來說是在 EngineResource 中定義一個 acquired 變數用來記錄圖襪指正片被引用的次數,調用 acquire() 方法會讓變數加1,調用 release() 方法會讓變數減1。

獲取圖片資源是先從弱引用取緩存,拿到的話,引用計數+1;沒有的話從LruCache中拿緩存,拿到的話,引用計數逗枝也是+1,同時把圖片從LruCache緩存轉移到弱應用緩存池中;再沒有的話就通過 EngineJob 開啟線程池去載入圖片,拿到的話,引用計數也是+1,會把圖片放到弱引用。

存數據
很明顯,這是載入圖片之後的事情。通過 EngineJob 開啟線程池去載入圖片,取到數據之後,會回調到主線程,把圖片存到弱引用。當圖片不再使用的時候,比如說暫停請求或者載入完畢或者清除資源時,就會將其從弱引用中轉移到告悔 LruCache 緩存池中。 總結一下,就是正在使用中的圖片使用 弱引用 來進行緩存,暫時不用的圖片使用 LruCache 來進行緩存的功能;同一張圖片只會出現在 弱引用 和 LruCache 中的一個。

為什麼要引入軟引用?
1、分壓策略,減少Lrucache 中 trimToSize 的概率。如果正在remove的是張大圖,lrucache正好處在臨界點,此時remove操作,將延緩Lrucache的 trimToSize 操作;
2 提高效率:弱引用用的是 HashMap ,Lrucache用的是 LinkedHashMap ,從訪問效率而言,肯定是 HashMap 更高。

Glide磁碟緩存策略(4.x)

如果在內存緩存中沒獲取到數據會通過 EngineJob 開啟線程池去載入圖片,這里有2個關鍵類: DecodeJob 和 EngineJob 。 EngineJob 內部維護了線程池,用來管理資源載入,當資源載入完畢的時候通知回調; DecodeJob 是線程池中的一個任務。

磁碟緩存是通過 DiskLruCache 來管理的,根據緩存策略,會有2種類型的圖片, DATA (原始圖片)和 RESOURCE (轉換後的圖片)。磁碟緩存依次通過 ResourcesCacheGenerator 、 SourceGenerator 、 DataCacheGenerator 來獲取緩存數據。 ResourcesCacheGenerator 獲取的是轉換過的緩存數據; SourceGenerator 獲取的是未經轉換的原始的緩存數據; DataCacheGenerator 是通過網路獲取圖片數據再按照按照緩存策略的不同去緩存不同的圖片到磁碟上。

Glide緩存分為 弱引用+ LruCache+ DiskLruCache ,其中讀取數據的順序是:弱引用 > LruCache > DiskLruCache>網路;寫入緩存的順序是:網路 --> DiskLruCache--> LruCache-->弱引用

內存緩存分為弱引用的和 LruCache ,其中正在使用的圖片使用弱引用緩存,暫時不使用的圖片用 LruCache緩存,這一點是通過 圖片引用計數器(acquired變數)來實現的,詳情可以看內存緩存的小結。

磁碟緩存就是通過DiskLruCache實現的,根據緩存策略的不同會獲取到不同類型的緩存圖片。它的邏輯是:先從轉換後的緩存中取;沒有的話再從原始的(沒有轉換過的)緩存中拿數據;再沒有的話就從網路載入圖片數據,獲取到數據之後,再依次緩存到磁碟和弱引用。

參考:
面試官:簡歷上最好不要寫Glide,不是問源碼那麼簡單
原來面試的時候寫精通Glide,這樣問我這樣答

❼ Android基礎 (11) PopupWindow詳解

(1)PopupWindow的使用
(2)自定義一個PopupWindow
(3)PopupWindow的源碼分析
(4)AlertDialog,popupWindow,Activity區別
(5)Activity-Window-View三者的差別

Android的對話框有兩種:PopupWindow和AlertDialog。它們的不同點在於:

PopupWindow的位置按照有無偏移分,可以分為偏移和無偏移兩種;按照參照物的不同,可以分為相對於某個控制項(Anchor錨)和相對於父控制項。具體如下:
showAsDropDown(View anchor):相對某個控制項的位置(正左下方),無偏移
showAsDropDown(View anchor, int xoff, int yoff):相對某個控制項的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y):相對於父控制項的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以設置偏移或無偏移。

使用詳述: https://blog.csdn.net/xiaanming/article/details/9121383

這里的WRAP_CONTENT可以換成fill_parent 也可以是具體的數值,它是指PopupWindow的大小,也就是contentView的大小,注意popupWindow根據這個大小顯示你的View,如果你的View本身是從xml得到的,那麼xml的第一層view的大小屬性將被忽略。相當於popupWindow的width和height屬性直接和第一層View相對應。

執行了一個attachToAnchor,意思是PopupWindow類似一個錨掛在目標view的下面,這個函數主要講xoff、yoff(x軸、y軸偏移值)、gravity(比如Gravity.BOTTOM之類,指的是PopupWindow放在目標view哪個方向邊緣的位置)這個attachToAnchor有點意思,通過弱引用保存目標view和目標view的rootView(我們都知道:通過弱引用和軟引用可以防止內存泄漏)、這個rootview是否依附在window、還有保存偏差值、gravity

PopupWindow通過為傳入的View添加一層包裹的布局,並重寫該布局的點擊事件,實現點擊PopupWindow之外的區域PopupWindow消失的效果

封裝庫可前往:#### https://github.com/yangchong211/YCDialog

❽ Android App內存優化

內存優化就是對內存問題的一個預防和解決,做內存優化能讓應用掛得少、活得好和活得久。

掛的少:
「掛」指的是 Crash,內存問題導致 Crash 的具體表現就是內存溢出異常 OOM。

活得好:
活得好指的是使用流暢,Android 中造成界面卡頓的原因有很多種,其中一種就是由內存問題引起的。內存問題之所以會影響到界面流暢度,是因為垃圾回收(GC,Garbage Collection),在 GC 時,所有線程都要停止,包括主線程,當 GC 和繪制界面的操作同時觸發時,繪制的執行就會被擱置,導致掉幀,也就是界面卡頓。

活得久:
活得久指的是我們的應用在後台運行時不會被幹掉。Android 會按照特定的機制清理進程,清理進程時優先會考慮清理後台進程。清理進程的機制就是LowMemoryKiller。在 Android 中不同的進程有著不同的優先順序,當兩個進程的優先順序相同時,低殺會優先考慮幹掉消耗內存更多的進程。也就是如果我們應用佔用的內存比其他應用少,並且處於後台時,我們的應用能在後台活下來,這也是內存優化為我們應用帶來競爭力的一個直接體現。

內存佔用是否越少越好?
當系統 內存充足 的時候,我們可以多用 一些獲得更好的性能。當系統 內存不足 的時候,我們希望可以做到 」用時分配,及時釋放「。內存優化並不能一刀切。

我們都知道,應用程序的內存分配和垃圾回收都是由Android虛擬機完成的,在Android 5.0以下,使用的是Dalvik虛擬機,5.0及以上,則使用的是ART虛擬機。
Android虛擬機Dalvik和ART

1、內存區域劃分

詳細請看以下兩篇文章(建議全看):
java內存四大區_JVM內存區域劃分
Android 內存機制

2、內存回收

垃圾收集的標記演算法(找到垃圾):

垃圾收集演算法(回收垃圾):

引用類型:強引用、軟引用、弱引用、虛引用

對象的有效性=可達性+引用類型

JAVA垃圾回收機制-史上最容易理解看這一篇就夠了
Android:玩轉垃圾回收機制與分代回收策略

android中還存在低殺機制,這種情況屬於系統整機內存不足,直接把應用進程殺掉的情況。

Android後台殺死系列:LowMemoryKiller原理

1、內存溢出
系統會給每個App分配內存空間也就是heap size值,當app佔用的內存加上申請的內存超過這個系統分配的內存限額,最終導致OOM(OutOfMemory)使程序崩潰。

通過命令 getprop |grep dalvik.vm.heapsize 可以獲取系統允許的最大
注意:在設置了heapgrowthlimit的狀況下,單個進程可用最大內存為heapgrowthlimit值。在android開發中,若是要使用大堆,須要在manifest中指定android:largeHeap為true,這樣dvm heap最大可達heapsize。
關於heapsize & heapgrowthlimit

2、內存泄漏
Android系統虛擬機的垃圾回收是通過虛擬機GC機制來實現的。GC會選擇一些還存活的對象作為內存遍歷的根節點GC Roots,通過對GC Roots的可達性來判斷是否需要回收。內存泄漏就是 在當前應用周期內不再使用的對象被GC Roots引用,造成該對象無法被系統回收,以致該對象在堆中所佔用的內存單元無法被釋放而造成內存空間浪費,使實際可使用內存變小。簡言之,就是 對象被持有導致無法釋放或不能按照對象正常的生命周期進行釋放。
Android常見內存泄漏匯總

3、內存抖動
指的是在短時間內大量的新對象被實例化,運行時可能無法承載這樣的內存分配,在這種情況下就會導致垃圾回收事件被大量調用,影響到應用程序的UI和整體性能,最終可能導致卡頓和OOM。
常見情況:在一些被頻繁調用的方法內不斷地創建對象。例如在View 的onDraw方法內new 一些新的對象。

注意內存抖動也會導致 OOM,主要原因有如下兩點:

1、Android Studio Profiler

作用

優點

內存抖動問題處理實戰

理解內存抖動的概念的話,我們就能明白只要能找到抖動過程中所產生的對象及其調用棧,我們就能解決問題,剛好Android Studio 的Porfiler裡面的Memory工具就能幫我們記錄下我們操作過程中或靜止界面所產生的新對象,並且能清晰看到這些對象的調用棧。

選擇Profile 中 的Memory ,選擇 Record Java/Kotlin allocations,再點擊Record開始記錄, Record Java/Kotlin allocations 選項會記錄下新增的對象。

操作完成之後,點擊如圖所示的紅腦按鈕,停止記錄。

停止記錄後,我們就可以排序(點擊 Allocations可以排序)看看哪些對象或基本類型在短時間被頻繁創建多個,點擊這些新增的對象就可以看到它的完成的調用鏈了,進而就找找到導致內存抖動的地方在哪裡了。

2、利用DDMS 和 MAT(Memory Analyzer tool)來分析內存泄漏

我們利用工具進行內存泄漏分析主要是用對比法:
a.先打開正常界面,不做任何操作,先抓取一開始的堆文件。
b.一頓胡亂操作,回到原來操作前的界面。主動觸發一兩次GC,過10秒再抓取第二次堆文件。
c.通過工具對比,獲取胡亂操作後新增的對象,然後分析這些新增的對象。

DDMS作用:抓取堆文件,主動觸發GC。(其實也是可以用Android Studio 的Profile裡面的Memory工具來抓取堆文件的,但是我這邊在利用Profile 主動觸發gc 的時候會導致程序奔潰,也不知道是不是手機的問題,所以沒用Android Studio的Profiler)

MAT作用:對堆文件進行對比,找到多出的對象,找到對象的強引用調用鏈。

以下是詳細的過程:

步驟1.打開DDMS,選擇需要調試的應用,打開初始界面,點擊下圖的圖標(Dump Hprof File)先獲取一次堆文件。

步驟2.對應用隨便操作後,回到一開始的界面,先多觸發幾次GC ,點擊下圖的圖標(Cause Gc)來主動觸發GC,然後再次點擊 Dump Hprof File 圖標來獲取堆文件。

步驟3.通過Android Studio Profile 或者 DDMS mp 的堆文件無法在MAT 打開,需要藉助android sdk包下的一個工具hprof-conv.exe來轉換。

格式為 hprof-conv 舊文件路徑名 要轉換的名稱;
例如:hprof-conv 2022-04-13_17-54-40_827.hprof change.hprof

步驟4.把兩份堆文件導入MAT,然後選擇其中第二次獲取的堆文件,點擊 如圖所示的 Histogram查看。

步驟5.點擊下圖圖標,Compare To Another Heap Dump ,選擇另一份堆文件。

6.會得出下圖所示的 Hitogram 展示,我們主要看Objects 這一列。 如下圖所示 「+ 2」 則代表前面兩份堆文件對比,這個對象多了兩個,我們主要就是要分析這些多了出來,沒有被回收的對象。

7.加入我們從增加的對象中,看到了MainActivity ,則需要從一開始打開的Hitogram 展示裡面找到這個對象的調用棧。如下圖所示,搜索MainActivity

8.看到下圖所示解僱,然後滑鼠右鍵點擊下圖紅色圈圈著的MainActivity ,選擇 Merger Shortest Paths to Gc Roots ,再選擇 exclude all phantom/weak/soft etc.references ,就可以看到這個MainActivity 對象的強引用鏈,至此我們就可以找到MainActivity對象是被什麼引用導致無法回收了。

3、內存泄露檢測神器之LeakCanary(線下集成)

自行學習了解,接入簡單,使用簡單,基本可以解決大部分內存泄漏問題。
github地址 : https://github.com/square/leakcanary/
學習地址 : https://square.github.io/leakcanary/changelog/#version-22-2020-02-05

針對內存抖動的建議:

針對內存泄漏問題的建議:

針對內存溢出問題的建議(主要就是要減少內存佔用):

建議參考:
深入探索 Android 內存優化(煉獄級別)

對於 優化的大方向,我們應該優先去做見效快的地方,主要有以下三部分:內存泄漏、內存抖動、Bitmap。完善監控機制也是我們的重點,能幫助我們對內存問題快速分析和處理。

參考:
深入探索 Android 內存優化(煉獄級別)

❾ Android 內存回收機制

新生代的內存區域又被分成三部分,分別是Eden、s0、s1,在hotspot中它們的默認是比例是8:1:1,為什麼是這個比例下面會解釋。每次分配新對象都是從Eden中分配,新生代的gc過程是,通過gc root對象(gc root對象包括:在棧幀中的對象、native棧中的對象、靜態對象)標記存活的對象,並且把存活的對象拷貝到s0中然後清空Eden,接下來的gc又會把Eden和s0存活的對象拷貝到s1中,s0和是s1總有一個是空閑的,gc過程就是把Eden和其中一個s的存活對象拷貝到另一個s中,然後清空s和Eden。為什麼Eden:s0:s1是8:1:1呢?那是因為新生代對象經過一次gc後存活的概率只有5%左右,之前IBM統計過,正是因為新生代經過gc後存活的對象很少,才會使用拷貝擦除這種方法。gc最快的方法就是把沒有被gc root對象直接引用或者間接引用的對象標記為無效,但是這樣勢必會造成大量的內存碎片,所以綜合考慮最終在新生代使用拷貝擦除這種演算法

在新生代中經過多次gc後仍然存活的對象則會晉升為老年代對象。老年代對象的gc比新生代更耗時。
老年代的gc過程是:

由於Android作為一個終端,需要快速的響應用戶的操作,而gc過程又要暫停所有的線程,所以必須要保證的gc的帆段核時間不會太長。在Android中應用啟動的時候一般會分配一段內存作為初始內存,在應用燃銀的運行過程需要創建一個新對象,而初始分配的內存空間已經無法提供足夠的內存,此時就會觸發gc,如果gc過後還是沒有足夠內存則會對堆內存進行擴容,擴容到最大值後還是沒有提供足夠的內存則會再進行一次gc,這次gc會把軟引用也清空,如果仍然沒有足夠的內存就拋出oom。

總結起來 Android系統不會一次性就把堆內存分配給應用進程,這態掘樣會導致gc的時間很長,用戶的操作長時間得不到響應,而是分步給應用進程的堆內存進行擴容直到最大限制值

❿ Android內存優化三:內存泄漏檢測與監控

Android內存優化一:java垃圾回收機制
Android內存優化二:內存泄漏
Android內存優化三:內存泄漏檢測與監控
Android內存優化四:OOM
Android內存優化五:Bitmap優化

Memory Profiler 是 Profiler 中的其中一個版塊,Profiler 是 Android Studio 為我們提供的性能分析工具,使用 Profiler 能分析應用的 CPU、內存、網路以及電量的使用情況。

進入了 Memory Profiler 界面。

點擊 Record 按鈕後,Profiler 會為我們記錄一段時間內的內存分配情況。

在內存分配面板中,通過拖動時間線來查看一段時間內的內存分配情況

通過搜索類或者報名的方式查看對象的使用情況

使用Memory Profiler 分析內存可以查看官網: 使用內存性能分析器查看應用的內存使用情況

對於內存泄漏問題,Memory Profiler 只能提供一個簡單的分析,不能夠確認具體發生問題的地方。

而 MAT 就可以幫我們做到這一點,它是一款功能強大的 Java 堆內存分析工具,可以用於查找內存泄漏以及查看內存消耗情況。

as 生成hprof文件無法被mat識別,需要進行轉換

使用hprof-conv進行轉換,hprof-conv位於sdkplatform-tools

ps:as導出hprof前最好先gc幾次,可排除一些干擾

Histogram 可以列出內存中的對象,對象的個數以及大小; Dominator Tree 可以列出那個線程,以及線程下面的那些對象佔用的空間; Top consumers 通過圖形列出最大的object; Leak Suspects 通過MA自動分析泄漏的原因。

Shallow Heap就是對象本身佔用內存的大小,不包含其引用的對象內存,實際分析中作用不大。常規對象(非數組)的ShallowSize由其成員變數的數量和類型決定。數組的shallow size有數組元素的類型(對象類型、基本類型)和數組長度決定。對象成員都是些引用,真正的內存都在堆上,看起來是一堆原生的byte[], char[], int[],對象本身的內存都很小。

Retained Heap值的計算方式是將Retained Set(當該對象被回收時那些將被GC回收的對象集合)中的所有對象大小疊加。或者說,因為X被釋放,導致其它所有被釋放對象(包括被遞歸釋放的)所佔的heap大小。

Path To GC Roots -> exclude all phantim/weak/soft etc. references:查看這個對象的GC Root,不包含虛、弱引用、軟引用,剩下的就是強引用。從GC上說,除了強引用外,其他的引用在JVM需要的情況下是都可以 被GC掉的,如果一個對象始終無法被GC,就是因為強引用的存在,從而導致在GC的過程中一直得不到回收,因此就內存泄漏了。

List objects -> with incoming references:查看這個對象持有的外部對象引用

List objects -> with outcoming references:查看這個對象被哪些外部對象引用

使用對象查詢語言可以快速定位發生泄漏的Activity及Fragment

使用 MAT 來分析內存問題,效率比較低,為了能迅速發現內存泄漏,Square 公司基於 MAT 開源了 LeakCanary ,LeakCanary 是一個內存泄漏檢測框架。

集成LeakCanary後,可以在桌面看到 LeakCanary 用於分析內存泄漏的應用。

當發生泄漏,會為我們生成一個泄漏信息概覽頁,可以看到泄漏引用鏈的詳情。

LeakCanary 會解析 hprof 文件,並且找出導致 GC 無法回收實例的引用鏈,這也就是泄漏蹤跡(Leak Trace)。

泄漏蹤跡也叫最短強引用路徑,這個路徑是 GC Roots 到實例的路徑。

LeakCanary 存在幾個問題,不同用於線上監控功能

線上監控需要做的,就是解決以上幾個問題。

各大廠都有開發線上監控方案,比如快手的 KOOM ,美團的 Probe ,位元組的 Liko

快手自研OOM解決方案KOOM今日宣布開源

總結一下幾點:

通過無性能損耗的 內存閾值監控 來觸發鏡像採集。將對象是否泄漏的判斷延遲到了解析時

利用系統內核COW( Copy-on-write ,寫時復制)機制,每次mp內存鏡像前先暫停虛擬機,然後fork子進程來執行mp操作,父進程在fork成功後立刻恢復虛擬機運行,整個過程對於父進程來講總耗時只有幾毫秒,對用戶完全沒有影響。

熱點內容
如何在安卓上讓蘋果耳機彈窗 發布:2025-02-13 11:38:13 瀏覽:191
搭建自己的伺服器直播間 發布:2025-02-13 11:27:34 瀏覽:986
酷狗音樂試聽緩存刪了會怎樣 發布:2025-02-13 11:02:12 瀏覽:267
python游戲服務端 發布:2025-02-13 11:00:19 瀏覽:927
雲原生伺服器 發布:2025-02-13 10:55:34 瀏覽:827
linuxip命令查看ip 發布:2025-02-13 10:49:45 瀏覽:421
java基礎應用 發布:2025-02-13 10:44:53 瀏覽:711
linux內核搶占 發布:2025-02-13 10:36:32 瀏覽:890
家裝公司源碼 發布:2025-02-13 10:35:35 瀏覽:49
aspnet更新資料庫 發布:2025-02-13 10:35:34 瀏覽:385