01.13 Dart虛擬機啟動過程,虛擬機是怎麼工作的

Dart虛擬機概述

Dart虛擬機擁有自己的Isolate,完全由虛擬機自己管理的,Flutter引擎也無法直接訪問。Dart的UI相關操作,是由Root Isolate通過Dart的C++調用,或者是發送消息通知的方式,將UI渲染相關的任務提交到UIRunner執行,這樣就可以跟Flutter引擎相關模塊進行交互。

Isolate之間內存並不共享,而是通過Port方式通信,每個Isolate是有自己的內存以及相應的線程載體。從字面上理解,Isolate是“隔離”,isolate之間的內是邏輯隔離的。Isolate中的代碼也是按順序執行,因為Dart沒有共享內存的併發,沒有競爭的可能性,故不需要加鎖,也沒有死鎖風險。對於Dart程序的併發則需要依賴多個isolate來實現。

DartVM啟動工作

AndroidShellHolder對象的創建過程,會調用到DartVMRef::Create(),進行DartVM創建,主要是為Dart虛擬機解析數據DartVMData,註冊一系列Native方法,創建名專屬vm的Isolate對象,初始化虛擬機內存、堆、線程、StoreBuffer等大量對象,工作內容如下:

  1. 同一個進程只有一個Dart虛擬機,所有的Shell共享該進程中的Dart虛擬機,當leak_vm為false則在最後一個Shell對象退出時會回收dart虛擬機, 當leak_vm為true則即便Shell對象全部退出也不會回收dart虛擬機,這是為了優化再次啟動的速度;
  2. 創建的IsolateNameServer對象,裡面有一個重要的成員port_mapping_,以端口名為key,端口號為value的map結構,記錄所有註冊的port端口; 可通過RegisterIsolatePortWithName()註冊Isolate端口,通過LookupIsolatePortByName()根據端口名來查詢端口號;
  3. 創建DartVMData對象,從settings中解析出vm_snapshot,isolate_snapshot這兩個DartSnapshot對象,DartSnapshot裡有data_和instructions_兩個字段;
  4. 創建ListeningSocketRegistry對象,其中有兩個重要的成員變量sockets_by_port_(記錄以端口號為key的socket集合),sockets_by_fd_(記錄以fd為key的socket集合);
  5. 通過pthread_create創建名為”dart:io EventHandler”的線程,然後進入該線程進入poll輪詢方法,一旦收到事件則執行HandleEvents()
  6. 執行DartUI::InitForGlobal():執行相關對象的RegisterNatives()註冊Native方法,用於Dart代碼調用C++代碼。創建DartLibraryNatives類型的g_natives對象,作為靜態變量,其成員變量entries_和symbols_分別用於記錄NativeFunction和Symbol信息;通過該對象的Register(),註冊dart的native方法,用於Dart調用C++代碼;通過GetNativeFunction(),GetSymbol()來查詢Native方法和符號信息。Canvas、DartRuntimeHooks、Paragraph、Scene、Window等大量對象都會依次執行RegisterNatives(g_natives)來註冊各種Native方法,
  7. 執行Dart::Init():傳遞的參數params記錄isolate和文件等相關callback,用於各種對象的初始化初始化VirtualMemory、OSThread、PortMap、FreeListElement、ForwardingCorpse、Api、NativeSymbolResolver、SemiSpace、StoreBuffer、MarkingStack對象初始化ThreadPool線程池對象創建名為”vm-isolate”的Isolate對象,注意此處不允許混淆符號,將新創建的isolate添加到isolates_list_head_鏈表;為該isolate創建Heap、ApiState等對象;創建IsolateMessageHandler,其繼承於MessageHandler,MessageHandler中有兩個比較重要的成員變量queue_和oob_queue_,用於記錄普通消息和oob消息的隊列。isolate需要有一個Port端口號,通過PortMap::CreatePort()隨機數生成一個整型的端口號,PortMap的成員變量map_是一個記錄端口entry的HashMap,每一個entry裡面有端口號,handler,以及端口狀態。

Dart代碼可以用兩種不同方式執行:一是通過一個原生的虛擬機;另一種則是JavaScript引擎,使用編譯器將Dart代碼轉換為JavaScript代碼。也就是說,你可以使用Dart編寫一個Web應用程序,並在任何現代瀏覽器上編譯及運行它。雖然目前Dart VM尚未集成至Chrome中,但已在研究計劃之中。

這門語言整體來說都還在進行中,結果如何誰也不知道。


分享到:


相關文章: