Unity3D实验室之iOS真机闪退的解决方法
问题的产生
这个问题一般发生在项目比较大,OO使用良好,泛型继承用的较多的时候。第一次真机测试时,项目终于进入真机测试阶段,之前都是在Unity编辑环境下开发测试,运行的都很良好,信心满满的打包安装,结果闪退。。。,各种代码调试,跟踪都没什么线索。这怎么办?问题很可能出在了AOT的设置上。
解决方案
这个通常是因为你的程序编译的时候给trampoline分配的空间太小,而你的程序中又大量使用了泛型、泛型方法调用和接口实现导致的。具体的解决方法就是在Unity3D的编译选项PlayerSetting中有一个AOTCompilationOptions条目,在这个选项条目中加上以下编译参数就好了
nrgctx-trampolines=8192,nimt-trampolines=8192,ntrampolines=4096
加上以后,重新打包测试,看还有没有问题
参数意思
关于上面的三个参数的意思分别如下:
nrgctx-trampolines=8192这是留给递归泛型使用的空间,默认是1024
nimt-trampolines=8192这是留给接口使用的空间,默认是128
ntrampolines=4096这是留给泛型方法调用使用的空间,默认是1024
什么是trampoline
Trampoline是一些手写的非常短小的用来在MonoRuntime中执行很多操作的ComponentCode。主要是通过JIT使用到的本地代码宏在运行时动态生成的。它们通常都有与之相对应的C方法,在某些较为复杂的场景中,当trampoline无法胜任时,mono运行时就会将这些复杂的操作交回给这些对应的C方法来执行。这也可以看作是将JIT代码的执行权交回给runtime的一种方式。
这看起来明显是为了提高monoruntime在执行C#代码时候的效率,但还是有点不明白。
再来看看官方文档关于JITTrampolines和AOTTrampolines的介绍:
JITTrampolines这些Trampoline主要是JIT在首次调用某个方法的时候编译方法用的。当JIT在编译一个方法调用指令时,它并不会立刻就编译这个被调用到的方法。实际上,它会先创建一个JITTrampoline,同时创建一个指向这个trampoline的调用指令。当这个JITTrampoline在调用到的时候,它会再调用mono_magic_trampoline()方法来编译这个trampoline实际指向的目标方法,然后将编译后的方法的指针地址返回给这个指向它的trampoline。这个过程呢稍微有点慢,所以呢,mono_magic_trampoline()方法会优化调用JIT代码的过程,它会先尝试调用已经通过JIT编译过的方法而不是立即通过trampoline直接进行调用。这些都是通过在tramp-.c文件中的mono_patch_callsiete()方法来完成的。
AOTTrampolines
AOTTrampolines和JITTrampolines非常相似,但是AOTTrampolines接受的编译参数不是一个Mono方法而是一个image+token对。如果传入的用于编译的image+token对所指向的方法已经经过AOT编译过了,那么再次编译这个image+token对时,就会直接返回这个已编译方法的指针地址而不需要再次加载这个方法的元数据进行再次编译了。
IMTTrampolines也是用于优化接口调用效率的。
Trampolines存在的价值就是为了减少C#代码在monoruntime中运行时的性能损耗,提高C#代码的执行效率。
总结
当遇到类似问题时可以试试上面的方法。
以上这篇Unity3D实验室之iOS真机闪退的解决方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。