在做一些大项目的时候,在开发的时候运行的非常完美,但是项目打包成IOS有可能可以运行或者也可以进入游戏,但是在游戏中做某个操作莫名其妙的出现崩溃的问题( 不是100%出现 )。一般遇到这样的问题,就是看错误日志,但是错误的日志是一些 内存地址 ,或者可以把 内存地址转为符号化 。很有可能就是束手无措的感觉。
尝试在Unity中将 Player Setting->Other->AOT Compilation Options 设置为 nrgctx-trampolines=8192,nimt-trampolines=8192,ntrampolines=4096
因为没有设置这个而导致奔溃闪退的原因是默认Mono Runtime在AOT编译的时候给的trampoline配置太小,不适合我们这种设计优良,大量使用interface,设计绝对遵照OO思想的稍大一些的项目。 AOT就是区别于JIT(Just In Time)的另一个编译机制,全称是Ahead Of Time,就是预先编译好,而不是在代码执行到了某个方法再进行编译,这样的话会有一些好处。 使用 AOT 编译的有点有以下优点:
AOT默认编译时给Trampolines的参数有点低:
这对于小一些的项目可能是够用的,因为整体项目的结构不会太复杂,使用到的接口、泛型、递归相对也不会太多,但是对于一个稍大一些的项目来说,特别是采用了某些设计良好的第三方库的项目来说,这就可能不够用了。
大概解释一下相关的几个名词:
Trampoline是一些手写的非常短小的用来在mono运行时中执行很多操作的组件代码。主要是通过JIT使用到的本地代码宏在运行时动态生成的。它们通常都有与之相对应的C方法,在某些较为复杂的场景中,当trampoline无法胜任时,mono运行时就会将这些复杂的操作交回给这些对应的C方法来执行。这也可以看作是将JIT代码的执行权交回给runtime的一种方式。
JIT Trampolines这些Trampoline主要是JIT在首次调用某个方法的时候编译方法用的。当JIT在编译一个方法调用指令时,它并不会立刻就编译这个被调用到的方法。实际上,它会先创建一个JIT Trampoline,同时创建一个指向这个trampoline的调用指令。当这个JIT Trampoline在调用到的时候,它会再调用 mono_magic_trampoline() 方法来编译这个trampoline实际指向的目标方法,然后将编译后的方法的指针地址返回给这个指向它的trampoline。这个过程呢稍微有点慢,所以呢, mono_magic_trampoline() 方法会优化调用JIT代码的过程,它会先尝试调用已经通过JIT编译过的方法而不是立即通过trampoline直接进行调用。这些都是通过在tramp-.c文件中的 mono_patch_callsiete() 方法来完成的。
mono_magic_trampoline()
mono_patch_callsiete()
AOT Trampolines和JIT Trampolines非常相似,但是AOT Trampolines接受的编译参数不是一个Mono方法而是一个image+token对。如果传入的用于编译的image+token对所指向的方法已经经过AOT编译过了,那么再次编译这个image+token对时,就会直接返回这个已编译方法的指针地址而不需要再次加载这个方法的元数据进行再次编译了。
原文链接: https://www.jianshu.com/p/252462b23252