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
相关文章
相关标签/搜索