Unity實現c#熱更新方案探究(二)

轉載請標明出處:http://www.cnblogs.com/zblade/
1、IOS對DLL熱更新的禁止
緊接上文,繼續對C#熱更新的研究。上文中,已經說了如何基於appDomain來實現對DLL的加載和卸載,進一步,能夠在unity工程中,將Dll打包成資源,經過Assembly.Load的方式加載DLL來實現更新。那麼爲何IOS中就不能這樣操做了呢?
推薦閱讀文章:
這兩篇文章,對整個IOS不能熱更新的原因,有詳細的講解,對於Mono的JIT編譯模式和AOT編譯模式也有講解。總結來講,就是因爲IOS的Full AOT編譯模式,不容許在IOS系統中動態生成代碼(代碼是能夠在IOS中動態生成的,只是IOS爲了安全性的考慮,禁止了內存的操做權限),因此JIT這種編譯模式被Mono本身就禁止了(IOS下)。
既然不能JIT的編譯,那麼咱們就不能基於Assembly.Load來加載DLL的bytes了。如何解決這個問題?讓咱們看看ILRuntime的解決思路。
 
2、ILRuntime基於IL虛擬機實現對DLL的熱更新
首先看看ILRuntime對於其實現原理的解釋:
ILRuntime藉助Mono.Cecil庫來讀取DLL的PE信息,以及當中類型的全部信息,最終獲得方法的IL彙編碼,而後經過內置的IL解譯執行虛擬機來執行DLL中的代碼
那麼,咱們逐步來分析這些操做過程是如何執行的。
一、藉助Mono.Ceil庫來讀取DLL的PE信息以及當中類型的全部信息
這一步是如何實現的,跟隨源代碼作一個詳細的跟蹤。
首先,是構建一個全局的appDomain(這兒不是程序域的意思,只是取其名字意思來表示)

 

 基於WWW的方式加載AssetBundle或者DLL/PDB後,接下來是將其封入到MemoryStream中,將dll和pdb的bytes都存入到內存流中後,執行其內部實現的LoadAssembly方法。

關鍵的是第一行,從Mono中加載模塊:html

 
進一步跟蹤:
ReadImageFrom的操做:

 

 其中ImageReader最終來自BinaryReader:
 

那麼接下來的ReadImage操做:安全

這四個操做,是最核心的操做,分別讀取DLL的PE的各個信息,這樣咱們就進入下一個步驟。
二、最終獲得方法的IL彙編碼
讓咱們分拆來看看這幾個讀取函數的實現
1)ReadOptionalHeaders
主要讀取PE的相關信息,不作過多解釋,能夠參看源碼閱讀理解;
2)ReadSections
讀取分塊數據
封裝一個Section,而後去執行讀取,而後賦值給section的Data,注意回退了Index
3)ReadCLIHeader
這步比較簡單

 

4) ReadMetadataapp

核心是兩個操做,一個是ReadMetadataStream,就是根據不一樣的標識符來新建不一樣的存儲結構;一個是ReadTableHeap:函數

初始化heap中的Table後,進行一次Compute,獲取size:編碼

而後填充size:
基於這四步操做,咱們能夠將IL的彙編碼存儲到Image中,而後進一步執行後續的CreateModule操做:
具體到,就是:
 
其中的ReadModule爲:
具體的讀取manifest和Module內部數據,能夠參看源碼。
讀取完module後,咱們下一篇文章再詳細講解如何執行IL語句,這篇文章先寫到這兒吧 :D
相關文章
相關標籤/搜索