99偷拍视频精品区一区二,口述久久久久久久久久久久,国产精品夫妇激情啪发布,成人永久免费网站在线观看,国产精品高清免费在线,青青草在线观看视频观看,久久久久久国产一区,天天婷婷久久18禁,日韩动漫av在线播放直播

手把手帶你了解內存抖動和泄漏的優化

前言
這個系列的文章:

1、用通俗易懂的講解方式,講解一門技術的實用價值
2、詳細書寫源碼的追蹤,源碼截圖,繪制類的結構圖,盡量詳細地解釋原理的探索過程
3、提供Github 的 可運行的Demo工程,但是我所提供代碼,更多是提供思路,拋磚引玉,請酌情cv
4、集合整理原理探索過程中的一些坑,或者demo的運行過程中的注意事項
5、用gif圖,最直觀地展示demo運行效果

創新互聯建站長期為1000多家客戶提供的網站建設服務,團隊從業經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯網生態環境。為蘄春企業提供專業的成都網站建設、網站制作蘄春網站改版等技術服務。擁有十余年豐富建站經驗和眾多成功案例,為您定制開發。

如果覺得細節太細,直接跳過看結論即可。本人能力有限,如若發現描述不當之處,歡迎留言批評指正。
手把手帶你了解內存抖動和泄漏的優化
學到老活到老,路漫漫其修遠兮。與眾君共勉 !,和我一起當個CV工程師吧,手動滑稽

正文大綱
  • jvm內存管理常識
  • 檢測以及處理內存抖動
  • 檢測以及處理內存泄漏
正文
jvm內存管理常識

LMK (LowMemoryKill)機制android底層會在系統內存告急的時候,按照一定規則殺死一些進程來滿足其他進程的內存需要。其中 消耗內存的高低就是其中一項指標,所以,優化app的內存占用,能夠有效降低app被系統殺死的概率。
GC STW機制GC,垃圾回收進程,在GC線程執行任務的時候,會存在一個 STW (stop the world) 機制,他就會把其他所有線程都掛起。如果GC非常頻繁地調用,那就會導致主線程不流暢,給用戶的感覺就是 卡頓。
內存抖動頻繁引起OOM內存抖動太頻繁,導致大量對象頻繁創建和銷毀,會產生大量不連續的內存空間,如果此時有一個大對象需要申請內存,就有可能申請失敗,導致 OOM內存溢出
一句話解釋 內存泄漏長生命周期的對象持有 短生命周期對象的強引用,在 短生命周期對象需要回收的時候發現 不能被回收,視為泄漏
GC回收 可達性分析
GC線程判定 一個對象是不是可以回收,是根據可達性分析算法,計算 GcRoot,從 GcRoot向下搜索,把 GcRoot沒有直接關聯的對象全部作為垃圾來回收。
強軟弱虛四大引用強和虛自不必說。強 最常見,沒有特殊處理的都是強引用(包括,匿名內部類會持有外部類的強引用)。虛引用沒什么用,不予討論。軟引用,用來定義一些還有用,但是不是必須的對象,使用 SoftRefrence<T>修飾,在內存緊張的時候,GC回收之后,使用 SoftRefrence<T>修飾,如果系統還有足夠的內存可用,那么軟引用關聯的對象就不會被回收。如果不足,則回收軟引用關聯的對象。弱引用( WeakRefrence<T>),比軟引用更弱一些,只要GC觸發,弱引用關聯的對象就會被回收。
注意: 使用軟和弱引用,要判定關聯對象是否為空。

檢測以及處理內存抖動
我們使用s開發,平時我們運行app,一般會點 RunApp,但是還有另一個選擇, 那就是 profileApp, 運行app起來之后,會在as下方看到profile 窗點擊之后,as下方會出現profile,圖中會顯示網絡,內存和cpu使用情況
手把手帶你了解內存抖動和泄漏的優化
手把手帶你了解內存抖動和泄漏的優化

如果內存的圖中抖動得非常明顯,比如像這樣的心電圖一樣:
手把手帶你了解內存抖動和泄漏的優化
那就說明非常明顯存在內存抖動,急需處理: 點擊內存圖形區域之后,就能看到詳細的內存變化情況,以及內存分配情況:
手把手帶你了解內存抖動和泄漏的優化
這里有個坑:

如果你從圖形中觀察到,內存走勢平穩,并沒有出現上滿模擬抖動的圖中那么夸張,是不是就不存在內存抖動呢?并不是。因為我們的gc,是在內存不可用的情況下才會去回收內存,如果app占用內存一直比較少,沒有觸及gc的臨界值,那么就不會出現 斷崖式下跌. 那么這樣就觀察不出內存抖動了,怎么辦呢?

解決方法在8.0以下的安卓手機上,在下方的位置上會出現一個Record按鈕(如果是8.0以上,你可以直接用拖拽的方式來截取一段內存record):
手把手帶你了解內存抖動和泄漏的優化
點擊它,一段時間之后,再點一下:你就能在下方發現一張表格:
手把手帶你了解內存抖動和泄漏的優化
這張表格代表的是,你Record這段時間之內創建的對象,點擊一下第二列 Allocations,對創建的數量進行排序,找出創建次數最多的對象:
手把手帶你了解內存抖動和泄漏的優化
然后,點擊排行第一的String之后,會在右方看到
手把手帶你了解內存抖動和泄漏的優化
然后點擊其中的一個,又會看到一個新的窗口:
手把手帶你了解內存抖動和泄漏的優化
此為止,就找到了 創建對象的 元兇,以這個為線索,找到你們自己包名下的類和方法,確定是我們自己的代碼在不合理地創建對象.

再往后,就是根據各自的業務代碼去做優化了,記住一個宗旨:不要讓代碼干多余的事。如果是我們調用了系統的api導致了不合理地大量對象的創建,那么就要考慮這個系統API為什么會這樣創建對象,有沒有其他方法避免嗎,從業務代碼層來合理使用這個api,實在不行再考慮自定義api或者換個系統api。

在我們做了一次優化之后,再profile運行一次app,再重復上面的過程。以此類推,直到內存抖動達到理想狀態。

總結

優化內存抖動,核心就是防止頻繁創建對象。常見的反面教材就是:循環中創建對象,大量調用的api中創建對象。而優化的主要手段,就是對象復用,常見的手段是:對象池,像是 Handler的Message 單鏈表池,Glide的bitmap池等。

檢測以及處理內存泄漏

經典案例:處理 handler異步任務導致的內存泄漏方法

  • 在Activity的onDestroy中移除所有的任務
    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacksAndMessages(null);//移除所有任務
    }
  • 使用靜態內部類 + Activity弱引用的方式
    MyHandler handler = new MyHandler(this);
    private  static class MyHandler extends Handler {
         WeakReference<Activity> activityWeakReference;
         MyHandler(Activity activity) {
               activityWeakReference = new WeakReference<>(activity);
         }
         @Override
         public void handleMessage(Message msg) {
               //在執行任務的時候,判斷弱引用所關聯的對象是否為空,能在對象已經被回收的情況下
               switch (msg.what) {
                   case 1:
                       if (activityWeakReference.get() !=null) {
                            //T0D0
                       }
               }
         }
    }
工具的使用

依然是 profileApp,先用 profile看出內存的變化情況。

問:如何判斷內存泄漏?

答:內存泄漏是精細功夫,不能全盤觀察,只能憑借profile的內存變化來推測。比如,打開app之后內存一路飆升,直到超出app能夠使用的最大內存,app崩潰,,這是最明顯的。又比如,你反復打開關閉某一個界面,發現內存的穩定線( 內存穩定之后,內存占用值)隨著每一次的打開關閉,都在提高,這說明,這一個界面上存在泄漏,有對象無法被回收。

上一章節使用 profile 最多是了解到 哪些對象的創建和回收引起了內存抖動,但是,涉及到泄漏,只通過profile尚且 不能知道是 哪個類持有了希望被回收的對象的強引用. 這里就要借助另外一款工具,他的名字叫做 EclipseMat (自行百度)

先回到剛才的 profile
手把手帶你了解內存抖動和泄漏的優化
點一下,然后再點一下,界面會自動跳轉:
手把手帶你了解內存抖動和泄漏的優化
手把手帶你了解內存抖動和泄漏的優化
點擊上面的保存按鈕,將文件存到本地;

然后:
手把手帶你了解內存抖動和泄漏的優化
但是這個文件是無法直接在mat打開的

找到SDK目錄下的要 hprof-conv.exe
手把手帶你了解內存抖動和泄漏的優化

使用cmd命令,對文件進行轉換,命令為:hprof-conv[源文件名][目標文件名]如 hprof-conv1.hprof2.hprof回車

將得到的 2.hprof利用剛才下載的Mat工具打開:
手把手帶你了解內存抖動和泄漏的優化
這里有很多指標,但是檢查內存泄漏,我們只需要關注這個直方圖按鈕即可:手把手帶你了解內存抖動和泄漏的優化

這個圖中會列出你dump的這一段內存中的所有對象,包括framework層的,也包括我們自己代碼創建的對象
手把手帶你了解內存抖動和泄漏的優化

案例模擬

我模擬了一個經典案例,也就是前面提到的 Handler延時任務導致 Activity不能被釋放,核心代碼如下

 public class SecondActivity extends AppComatActivity {
     Handler handler = new Handler();
     //創建一個強引用Activity的handler對象
     @Override
     protected void onCreate (Bundle savedInstancestate) {
           super.onCreate(saveInstanceState);
           setContentView(R.layout.activity_second);
           handler.postDelayed(new Runnable() {
                   @Override
                   public void run() {

                   }
           }, Integer.MAX_VALUE);
              //我讓任務永遠在這里
    }

我就用一個非常普通的方式創建了一個 handler對象,并且用它來執行一段延時任務,只不過,延時任務的延時時間是 Integer的最大值,也就是說,任務要很久以后才會執行。之后,我反復進出這一個 Activity,然后按照上面的方式 dump了一段 hprof,經過 hprof-conv 轉化,然后用 Mat打開:結果如下
手把手帶你了解內存抖動和泄漏的優化
我填寫過濾信息: SecondActivity 回車
手把手帶你了解內存抖動和泄漏的優化
在我們最終退出SecondActivity之后,內存中依然保留了 18個無用的對象。

那么是不是我們這18個都是泄漏的呢?
不一定
手把手帶你了解內存抖動和泄漏的優化
前文講過,只有不合理的強引用,才會導致內存泄漏,所以我們要按照上面的方式排除軟弱虛引用。之后我們能看到下面的界面,把能展開的信息盡數展開
手把手帶你了解內存抖動和泄漏的優化
了解 Handler源碼的同志們應該一眼就看明白了, handler引起了內存泄漏,是因為存在不合理地強引用鏈, 上圖中可以看出,最終是callback對象持有了 SecondActivity對象。

如何優化內存泄漏

我們剛才已經看到了Handler的不合理使用導致了內存泄漏,那么如果在 onDestroy中移除所有的任務

   @Override
    protected void onDestroy() {
          super.onDestroy();
          handler.removeCallbacksAndMessages(token.null):
    }
 }

執行同樣的任務,dump下來的hprof 在mat觸發了GC之后, SecondActivity數量變為了0,內存泄漏解決。

當然還有另一種做法,靜態內部類+弱引用。

ps:靜態內部類是為了防止內部類持有外部類的引用,弱引用是為了在GC觸發之時,回收掉WeakRefrence中的對象。

public class secondActivity extends AppCompatActivity {
Handler handler = new Handler():
@Override
protected void onCreate(Bundle saveInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
handler.postDelayed(runnable, Integer.MAX_VALUE);
//依舊是那個延時很久的任務
}
Runnable runnable = new MyRunnable(this);
private static class MyRunnable implements Runnable {
//靜態內部類
WeakReference&lt;activity&gt; activityWeakReference
//弱引用
MyRunnable(Activity activity) {
activityWeakReference = new WeakReference&lt;&gt;(activity);
}
@Override
public void run() {
}
}

手把手帶你了解內存抖動和泄漏的優化
手把手帶你了解內存抖動和泄漏的優化
但是排除之后,一個都沒有了。

小技巧

上面的步驟雖然可行,但是如果有很多頁面都需要排查泄漏,那么我們一個一個頁面去點開關閉,整個過程將會非常冗長難受。其實有辦法解決。回到之前的直方圖:
手把手帶你了解內存抖動和泄漏的優化
使用方法為:如果你想進行一個操作,你操作前后各dump一個hprof,命名為 before和after, 然后用hprof-conv轉換一下,變為 before 和 `after ,用eclipse mat同時打開這兩個文件,然后切換到after.hprof` ,點擊上圖中的按鈕

它會讓你選擇想要對比的文件,點擊before,然后過濾SecondActivity
手把手帶你了解內存抖動和泄漏的優化
這種方式可以在處理泄漏之前,事先排查可能泄露的代碼區域。簡化我們的優化工作。

結語

內存抖動和泄漏優化涉及到Jvm很多知識點,除了我之前列出的幾點之外,還有很多細枝末節。要做好 內存優化,需要扎實的JVM知識基礎。

分享標題:手把手帶你了解內存抖動和泄漏的優化
網頁鏈接:http://www.yijiale78.com/article48/pcsiep.html

成都網站建設公司_創新互聯,為您提供網站設計公司微信小程序企業建站App開發商城網站App設計

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

微信小程序開發