中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

android要如何進行內存管理

發布時間:2022-02-25 14:40:14 來源:億速云 閱讀:103 作者:小新 欄目:開發技術

這篇文章給大家分享的是有關android要如何進行內存管理的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

Java Heap

Java Heap,也就是 JVM 中的堆區。簡單回顧一下 JVM 中運行時數據區域的劃分:

android要如何進行內存管理

  • 橙色區域的方法棧以及程序計數器屬于線程私有,主要存儲方法中的局部數據。

  • 方法區主要存儲常量以及類信息,線程共享。

  • 堆區主要負責存儲創建的對象,幾乎一切對象的內存都在堆區中分配,同時也是線程共享。

我們在 android 程序中使用如 Object o = new Object() 代碼創建的對象都會在堆區中分配一塊內存進行存儲,具體如何分配由虛擬機解決而不需要我們開發者干預。當一個對象不再使用時, JVM 中具有垃圾回收機制(GC),會自動釋放堆區中無用的對象,重新利用內存。當我們請求分配的內存已經超過堆區的內存大小,則會拋出 OOM 異常。

在 android 中,堆區是一個由 JVM 邏輯劃分的區域,他并不是真正的物理區域。堆區并不會直接全部映射和他等量大小的物理內存,而是到了需要使用時,才會去建立邏輯地址和物理地址的映射:

android要如何進行內存管理

這樣可以給應用分配足夠的邏輯內存大小,同時也不必在啟動時一次性分配一大塊的物理內存。在相同大小的內存中,可以運行更多的程序。

當堆區進程 GC 之后,釋放出來多余的空閑內存,會返還給系統,減少物理內存的占用。但這個過程涉及到比較復雜的系統調用,若釋放的內存較為少量,可能得不償失,則無需返還給系統,在堆區中繼續使用即可。

在 GC 過程中,如果一個對象不再使用,但是其所占用的內存無法被釋放,導致資源浪費,這種現象稱為內存泄漏。內存泄露會導致堆區中的對象越來越多,內存的壓力越來越大,甚至出現 OOM 。因此,內存泄露是我們必須要盡量避免的現象。

進程內存分配

堆區的內存分配,屬于進程內的內存分配,由進程自己管理。下面講一個應用,系統是如何為其分配內存的。

系統的運行內存,即為我們常說的 RAM ,是應用的運行空間。每個應用必須裝入內存中才可以被執行:

android要如何進行內存管理

  • 我們安裝的應用進程都位于硬盤中

  • 當一個應用被執行時,需要裝入到 RAM 中才能被執行(zRAM 是為了壓縮數據節省空間而設計,后續會講到)

  • CPU 與 RAM 交互,讀取指令、數據、寫入數據等

RAM 的大小為設備的硬件內存大小,是非常寶貴的資源。現代手機常見的運存是6G、8G或者12G,一些專為游戲研發的手機甚至有18G,但同時價格也會跟上去。

Android 采用分頁存儲的方式把一個進程存儲到 RAM 中。分頁存儲,簡單來說就是把內存分割成很多個小塊,每個應用占用不同的小塊,這些小塊也可以稱為頁:

android要如何進行內存管理

前面講到,進程的堆區并不是一次性分配,當需要分配內存時,系統會為其分配空閑的頁;當這些頁被回收,那么有可能被返還到系統中。

這里的頁、塊概念涉及到操作系統的分頁存儲,這里并不打算展開詳細講解,有興趣的讀者可以自行了解:分頁存儲-維基百科。本文中的“頁”與“塊”可以不嚴謹地理解為同個概念,為了幫助理解這里不進行詳細地區分。

分配給進程的頁可以分為兩種類型:干凈頁、臟頁:

  • 干凈頁:進程從硬盤中讀取數據或申請內存之后未進行修改。這種類型的頁面在內存不足的時候可以被回收,因為頁中存儲的數據可通過其他的途徑復原。

  • 臟頁:進程對頁中的數據進行了修改或數據存儲。這類頁面不能被直接回收,否則會造成數據丟失,必須先進行數據存儲。

zRAM,是作為 RAM 中的一個分區,當內存不足時,可以把一些類型的頁壓縮之后存儲在zRAM中,當需要使用的時候再從zRAM中調出。通過壓縮來節省應用的空間占用,同時不需要與硬盤進行調度,提高了速度。

這里需要理解的一個點是:內存中的操作速度要遠遠比硬盤操作快。即使與zRAM的調入和調出需要壓縮和解壓,其速度也是比與硬盤交互快得多。

內存不足管理

前面我們一直強調,移動設備的內存容量是非常有限的,需要我們非常謹慎地去使用它。幸運的是,JVM 和 android 系統早就幫我們想到了這一點。

面對不同的內存壓力,android 會有不同的應對策略。從低到高依次是 GC、內核交換守護進程釋放內存、低內存終止守護進程殺死進程釋放內存;他們的代價也是逐步上升。下面我們依個來介紹一下。

GC 垃圾回收

GC 屬于 JVM 內部的內存管理機制,他管理的內存區域是堆區。當我們創建的對象越來多,堆區的壓力越來越大時,GC 機制就會啟動,開始回收堆區中的垃圾對象。

辨別一個對象是否是垃圾,虛擬機采用的是可達性分析法。即從一些確定活躍有用的對象出發,向下分析他的引用鏈;如果一個對象直接或者間接這些對象所引用,那么他就不是垃圾,否則就是垃圾。這些確定活躍有用的對象稱為 GC Roots:

android要如何進行內存管理

如上圖,其中綠色的對象被 GC Roots 直接或間接引用,則不會被回收;灰色的對象沒有被引用則被標記為垃圾
GC Roots對象的類型比較常見的是靜態變量以及棧中的引用。靜態變量比較好理解,他在整個進程的執行期間不會被回收,因此他肯定是有用的。棧,這里指的是 JVM 運行數據區域中的方法棧,也就是局部變量引用,在方法執行期間肯定是活躍的。由于方法棧屬于線程私有,因此這里等于活躍線程持有的對象不會被回收。

因此,如果一個對象對于我們的程序不再使用,則必須解除 GC Roots 對其的引用,否則會造成內存泄露。例如,不要把 activity 賦值給一個靜態變量,這樣會導致界面退出時activity無法被回收。

GC 也并不是直接對整個堆區進行回收,而是將堆區中的對象分成兩個部分:新生代、老年代。

剛創建的對象大都會被回收,而在多次回收中存活的對象則后續也很少被回收。新生代中存儲的對象主要是剛被創建不久的對象,而老年代則存儲著那些在多次 GC 中存活的對象。那么我們可以針對這些不同特性的對象,執行不同的回收算法來提高GC性能:

  • 對于新創建的對象,我們需要更加頻繁地對他們進行GC來釋放內存,且每次只需要記錄需要留下來的對象即可,而不必要去標記其他大量需要被回收的對象,提高性能。

  • 對于熬過很多次GC的對象,則可以以更低的頻率對他門進行GC,且每次只需要關注少量需要被回收的對象即可。

具體的垃圾回收算法就不繼續展開了,了解到這里就可以。感興趣的讀者可以閱讀相關書籍。

單次的垃圾回收速度是很快的,甚至我們都無法感知到。但當內存壓力越來越大,垃圾回收的速度跟不上內存分配的速度,此時就會出現內存分配等待 GC 的情況,也就是發生了卡頓。同時,我們無法控制 GC 的時機,JVM 有一套完整的算法來決定什么時候進行 GC。假如在我們滑動界面的時候觸發 GC ,那么展示出來的就是出現了掉幀情況。因此,做好內存優化,對于 app 的性能表現非常重要。

內核交換守護進程

GC 是針對于 Java 程序內部進行的優化。對于移動設備來說,RAM 非常寶貴,如何在有限的 RAM 資源上進行分配內存,也是一個非常重要的話題。

我們的應用程序都運行在 RAM 中,當進程不斷申請內存分配,RAM 的剩余內存達到一定的閾值時,會啟動內核交換守護進程來釋放內存以滿足資源的分配。

內核交換守護進程,是運行在系統內核的一個進程,他主要的工作時回收干凈頁、壓縮頁等操作來釋放內存。前面講到,android 是基于分頁存儲的操作系統,每個進程都會被存儲到一些頁中。分頁的類型有兩種:干凈頁、臟頁:

  • 當內核交換守護進程啟動時,他會把干凈頁回收以釋放內存。當進程再次訪問干凈頁時,則需要去硬盤中再次讀取。

  • 對于臟頁,內核交換守護進程會把他們壓縮后放入 zRAM 中。當進程訪問臟頁時,則需要從zRAM中解壓出來。

通過不斷回收和壓縮分頁的方式來釋放內存,以滿足新的內存請求。使用此方式釋放的內存也無法滿足新的內存請求時,android 會啟動低內存終止守護進程,來終止一些低優先級的進程。

低內存終止守護進程

當 RAM 的被占用內存達到一定的閾值,android 會根據進程的優先級,終止部分進程來釋放內存。當低內存終止守護進程啟動時,說明系統的內存壓力已經非常大了,這在一些性能較差的設備中經常出現。

進程的優先級從高到低排序如下,優先級更高的進程會優先被終止:

從上到下依次是:

  • 后臺應用:使用過的 app 會被緩存在后臺,下一次打開可以更加快速地進行切換。當內存不足時,此類應用會最快被殺死。

  • 上一個應用:例如從微信跳轉到瀏覽器,此時微信就是上一個應用。

  • 主屏幕應用:這是啟動器應用,也就是我們的桌面。如果這個進程被kill了,那么返回桌面時會暫時黑屏。

  • 服務:同步服務、上傳服務等等

  • 可覺察的應用:例如正在播放的音樂軟件,他可以被我們感知到,但是不在前臺。

  • 前臺應用:當前正在使用的應用,如果這個應用被kill了,需要向用戶報崩潰異常,此時的體驗是極差的。

  • 持久性(服務):這些是設備的核心服務,例如電話和 WLAN。

  • 系統:系統進程。這些進程被終止后,手機可能即將重新啟動,就像手機突然卡死重啟。

  • 原生:系統使用的極低級別的進程,例如我們的內核交換守護進程。

當內存不足,會按照上面的規則,從上到下來終止進程,獲得內存資源。這也就是為什么在 android 中我們的后臺應用一直被殺死。為了避免我們的應用被優化,內存優化就顯得非常重要了。

感謝各位的閱讀!關于“android要如何進行內存管理”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

广饶县| 白河县| 苏尼特左旗| 土默特右旗| 湖州市| 台湾省| 绥德县| 奉新县| 安泽县| 斗六市| 安化县| 泸西县| 广饶县| 瓮安县| 郓城县| 华亭县| 襄樊市| 会同县| 肃北| 怀柔区| 浑源县| 普安县| 潍坊市| 开封县| 潜江市| 罗定市| 新安县| 丽水市| 扎兰屯市| 宁海县| 准格尔旗| 滦南县| 来宾市| 凤阳县| 临夏市| 柘荣县| 隆化县| 广州市| 德惠市| 连平县| 荃湾区|