Dart 內存管理機制

Dart彙總請點擊這裏

Dart內存管理

Dart運行環境(VM)

和Android Art一樣,Flutter也對Dart源碼做了AOT編譯,直接將Dart源碼編譯成了本地字節碼,沒有了解釋執行的過程,提升執行性能。這裏重點關注Dart VM內存分配(Allocate)和回收(GC)相關的部分。

和Java顯著不同的是Dart的"線程"(Isolate)是不共享內存的,各自的堆(Heap)和棧(Stack)都是隔離的,並且是各自獨立GC的,彼此之間通過消息通道來通信。Dart天然不存在數據競爭和變量狀態同步的問題,整個Flutter Framework Widget的渲染過程都運行在一個isolate中。

在這裏插入圖片描述

Dart VM將內存管理分爲新生代(New Generation)和老年代(Old Generation)。

新生代(New Generation)

通常初次分配的對象都位於新生代中,該區域主要是存放內存較小並且生命週期較短的對象,比如局部變量。新生代會頻繁執行內存回收(GC),回收採用“複製-清除”算法,將內存分爲兩塊(圖中的from 和 to),運行時每次只使用其中的一塊(圖中的from),另一塊備用(圖中的to)。當發生GC時,將當前使用的內存塊中存活的對象拷貝到備用內存塊中,然後清除當前使用內存塊,最後,交換兩塊內存的角色。
在這裏插入圖片描述

老年代(Old Generation)

在新生代的GC中“倖存”下來的對象,它們會被轉移到老年代中。老年代存放生命力週期較長,內存較大的對象。老年代通常比新生代要大很多。老年代的GC回收採用“標記-清除”算法,分成標記和清除兩個階段。在標記階段會觸發停頓(stop the world),多線程併發的完成對垃圾對象的標記,降低標記階段耗時。在清理階段,由GC線程負責清理回收對象,和應用線程同時執行,不影響應用運行

在這裏插入圖片描述

可以看到,Dart VM借鑑了很多JVM的思路,Dart中產生內存泄露的方式也和Java類似,Java中很多排查內存泄露的思路和防止內存泄露的編程方法應該也可以借鑑過來

內存管理算法

GC(Garbage Collection),垃圾回收機制,簡單地說就是程序中及時處理廢棄不用的內存對象的機制,防止內存中廢棄對象堆積過多造成內存泄漏

常見的垃圾回收算法有引用計數法(Reference Counting)、標註並清理(Mark and Sweep GC)、拷貝(Copying GC)和逐代回收(Generational GC)等算法。

iOS端

Objective-C語言本身是支持垃圾回收機制的,但有平臺侷限性,僅限於Mac桌面系統開發中,而在iPhone和iPad等蘋果移動終端設備中是不支持垃圾回收機制的。在移動設備開發中的內存管理是採用MRC(Manual Reference Counting)以及iOS5以後的ARC(Automatic Reference Counting),本質都是RC引用計數,通過引用計數的方式來管理內存的分配與釋放,從而防止內存泄漏。

iOS採用引用計數算法回收內存,當對象引用計數爲0時,對象會執行反初始化方法並被回收。如果兩個對象互相引用對方,就會造成循環強引用,導致內存泄漏。

Android端

Android系統採用的是標註並刪除和拷貝GC,並不是大多數JVM實現裏採用的逐代回收算法,根搜索算法回收內存,該算法通過GC Roots作爲起點搜索,搜索通過的路徑稱爲引用鏈,當一個對象沒有被GC Roots的引用鏈連接的時候,這個對象就會被回收。即使A和B兩個對象互相引用對方,只要A和B都不在引用鏈上,這兩個對象都會被回收。

下圖中的每個圓節點代表對象,箭頭代表可達路徑,當圓節點與 GC Roots 存在可達路徑時,表示無法回收(黃色圓節點),反之則可以回收(藍色圓節點)。

在這裏插入圖片描述

GC Root

  • 虛擬機棧(棧幀中的局部變量)中的引用的對象。
  • 方法區域中的類靜態屬性引用的對象。
  • 方法區域中常量引用的對象。
  • 本地方法棧中 JNI(Native 方法)的引用的對象。
  • 運行中線程引用的對象
GC與引用計數RC的區別

引用計數RC和垃圾回收GC是有區別的。

  • GC垃圾回收是宏觀的,對整體進行內存管理,將所有對象看做一個集合,然後在GC循環中定時檢測活動對象和非活動對象,及時將用不到的非活動對象釋放掉來避免內存泄漏,也就是說用不到的垃圾對象是交給GC來管理釋放的,而無需開發者關心,比如Java中的垃圾回收機制;
  • 引用計數是局部性的,開發者要管理控制每個對象的引用計數,單個對象引用計數爲0後會馬上被釋放掉。ARC自動引用計數則是一種改進,由編譯器幫助開發者自動管理控制引用計數(自動在合適的時機發送release和retain消息)。另外自動釋放池autorelease pool則像是一個局部的垃圾回收,將部分垃圾對象集中釋放,相對於單個釋放會有一定延遲。
flutter

Flutter使用dart語言作爲其開發語言和運行環境。dart的runtime是一直存在的,但是在debug和release模式下有一些區別。

在debug模式下,dart大部分組件都放在設備上,例如runtime、JIT(Android)、interpreter(iOS)、debug和profile services。

在release模式下,只剩下runtime,而這也是Flutter App能夠運行起來的最基本組件。

在這裏插入圖片描述

發佈了80 篇原創文章 · 獲贊 44 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章