问题&解决

在做一些大项目的时候,在开发的时候运行的非常完美,但是项目打包成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的参数有点低:

  • nrgctx-trampolines 默认为 1024
  • nimt-trampolines 默认为 128
  • ntrampolines 默认为 1024

这对于小一些的项目可能是够用的,因为整体项目的结构不会太复杂,使用到的接口、泛型、递归相对也不会太多,但是对于一个稍大一些的项目来说,特别是采用了某些设计良好的第三方库的项目来说,这就可能不够用了。

大概解释一下相关的几个名词:

Trampoline

Trampoline是一些手写的非常短小的用来在mono运行时中执行很多操作的组件代码。主要是通过JIT使用到的本地代码宏在运行时动态生成的。它们通常都有与之相对应的C方法,在某些较为复杂的场景中,当trampoline无法胜任时,mono运行时就会将这些复杂的操作交回给这些对应的C方法来执行。这也可以看作是将JIT代码的执行权交回给runtime的一种方式。

JIT Trampolines

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() 方法来完成的。

AOT Trampolines

AOT Trampolines和JIT Trampolines非常相似,但是AOT Trampolines接受的编译参数不是一个Mono方法而是一个image+token对。如果传入的用于编译的image+token对所指向的方法已经经过AOT编译过了,那么再次编译这个image+token对时,就会直接返回这个已编译方法的指针地址而不需要再次加载这个方法的元数据进行再次编译了。

原文链接: https://www.jianshu.com/p/252462b23252

原文链接: https://www.jianshu.com/p/252462b23252 在做一些大 项目 的时候,在开发的时候 运行 的非常完美,但是 项目 打包成 IOS 有可能可以 运行 或者也可以进入游戏,但是在游戏中做某个操作莫名其妙的出现 崩溃 的问题(不是100%出现)。一般遇到这样的问题,就是看错误日志,但是错误的日志是一些内存地址,或者可以把内存地址转为符号化。很有可能就是束手无措的感觉。 网上查阅了一番,终于找到问题所在了,这个是 Unity 编译选项AOT设置问题(File->Build S 打开output_log.txt,如下: ... ... The file 'archive:/CAB-350107fab3529178780193de85391267/CAB-350107fab3529178780193de85391267' is corrupted! Remove it and launch unity again! [Position out of 游戏线上测试总是有一些很奇怪的crash信息上报, 闪退 点是 Unity 引擎C++层的方法GameObject::GetSupportedMessagesRecalculate。我们自己平时跑游戏,偶尔也会在场景切换的时候发生 闪退 。经过初步分析,确定是同一个crash。虽然收集到的 闪退 率不高,但既然我们自己人都碰到了,那线上实际情况可能会更容易出。 结论很简单,想看结论,直接跳到末尾即可。分析过程很坎坷,断断续续跨了有两三个月。分析过程分为两个阶段,阶段一主要是围绕 崩溃 点本身进行的分析,没有得出结论;阶段二,是 问题的产生 这个问题一般发生在 项目 比较大,OO使用良好,泛型继承用的较多的时候。第一次真机测试时, 项目 终于进入真机测试阶段,之前都是在 Unity 编辑环境下开发测试, 运行 的都很良好,信心满满的打包安装,结果 闪退 。。。,各种代码调试,跟踪都没什么线索。这怎么办?问题很可能出在了AOT的设置上。 这个通常是因为你的 程序 编译的时候给 trampoline 分配的空间太小,而你的 程序 中又大量使用了泛型、泛型方法调用和接口实现导致的。具体的解决方法就是在 Unity3D 的编译选项 Player Setting 中有一个 AOT Compilation Options 条目,在这个选项条目中加上 从错误堆栈中,你可以看到 闪退 发生时抛出的异常类型,也可以看到异常编码和抛出异常的线程。 0 CoreFoundation 0x2d6eaf9b + 154 1 libobjc.A.dylib 0x37f65ccf objc_exception_throw + 38 2 CoreF 大家可以试一下把许可证退还之后用 unity hub打开 项目 会有 闪退 ,但是提示信息是没有许可证相关的提示,这种情况下只需要将我们的许可证重新激活即可。下图我以 unity hub3.2.0-c5版本做解释点击添加完成先关后续步骤即可重新激活许可证这是我原来遇到最简单处理的一种。如果还不成功,可以将账号登出重新登录重新激活即可。