一次由图片引起的致命崩溃问题

项目上线后遭遇iOS9.x设备闪退难题,通过排查图片资源的DisplayGamut属性定位到问题根源,并提供了解决方案,涉及Xcode、Objective-C及iOS版本兼容性问题。

上周项目上线后出现一个奇怪的线上崩溃问题,写篇文章记录一下。

问题

系统为iOS9.0.2、iOS9.1、iOS9.2、iOS9.2.1的iPhone,通过App Store下载的,一启动程序就会闪退,但是在模拟器上或者真机debug模式相同系统版本的情况下也不会闪退。我们的项目环境为:Xcode9、Objective-C、Target iOS8.0及以上。

日志

下面列举几个常见的日志:

1、UIKit: -[UINibStringIDTable lookupKey:identifier:] + 132

	UIKit: -[UINibStringIDTable lookupKey:identifier:] + 132

UINibStringIDTable
2、UIKit: UINibDecoderDecodeObjectForValue + 788

UIKit: UINibDecoderDecodeObjectForValue + 788

UINibDecoderDecodeObjectForValue
3、CoreUI: -[CUIStructuredThemeStore renditionWithKey:usingKeySignature:] + 1600

CoreUI: -[CUIStructuredThemeStore renditionWithKey:usingKeySignature:] + 1600

CoreUI: -[CUIStructuredThemeStore renditionWithKey:usingKeySignature:] + 1600
4、libcache.dylib: _entry_get_optionally_checking_collisions + 164

libcache.dylib: _entry_get_optionally_checking_collisions + 164

libcache.dylib: _entry_get_optionally_checking_collisions + 164
5、FrontBoardServices: -[FBSSerialQueue _performNext] + 192

FrontBoardServices: -[FBSSerialQueue _performNext] + 192

FrontBoardServices: -[FBSSerialQueue _performNext] + 192
6、QuartzCore: CA::Context::commit_transaction(CA::Transaction*) + 340

QuartzCore: CA::Context::commit_transaction(CA::Transaction*) + 340

QuartzCore: CA::Context::commit_transaction(CA::Transaction*) + 340

解决

经网上查阅资料,发现Apple Developer Forums 上有一个跟我们近乎一样的问题(Crashes on iOS 9.0.2, 9.2 and 9.2.1)线上IPA包的图片资源中有3张图片的DisplayGamut是P3形式的(kCGColorSpaceDisplayP3是iOS9.3及以后才支持)。按如下几步操作即可解决:
1、导出线上IPA包,找到其中的Assets.car文件。
2、利用assetutil命令行工具将Assets.car文件导出为json格式,在终端进入Assets.car文件所在的文件夹下输入以下命令:

	sudo xcrun --sdk iphoneos assetutil --info Assets.car > Assets.json

3、打开第二步生成的Assets.json文件,查找DisplayGamut或者ARGB-16,包含此类信息的图片就是这次闪退问题的罪魁祸首了。替换一下对应的图片重新打包发布即可。
Assets.json

尾声

虽然及时解决了这个崩溃问题,但是今天回头又看了下,发现网上有个类似的问题(Release版本只在iOS9.2及以下闪退),对比了下,又稍微有些区别——原博主的是显示的图片格式问题,而我们项目中的却不是。PS:原博文介绍了另一种通过脚本处理所有图片格式的方法,本文就不列出了。我们有三张问题图片:
DisplayGamut
但是在Xcode中查看Color Space是正常的,如下所示:
flash_on

flash_off
然后对比了正常图片的Color Space也是sRGB IEC61966-2.1。因此,给本人带来一个疑惑,有待进一步证实~

补充说明

国庆假后得知业出现了很多类似问题,不过是Xcode10的bug,Apple也给出了回应,Xcode10.1会解决这个bug。
Asset Catalog
解决方案可以参考高老师很忙的微博: 解决Xcode10打包iOS9.0-iOS9.2.1Crash的问题

参考资料

[1]、Crashes on iOS 9.0.2, 9.2 and 9.2.1
[2]、App crashes as release build on iPad/iPhone 6-iOS 9.2 - but debugging is fine
[3]、App crashes immediately on start up… Crash in iOS9 on release only through TestFlight or Store. Distributed with Xcode 8
[4]、Release版本只在iOS9.2及以下闪退

### 常见JVM崩溃原因及解决方案 JVM(Java Virtual Machine)崩溃是指JVM在运行过程中由于某些异常情况导致进程异常终止。JVM崩溃通常表现为`hs_err_pid`日志文件的生成,其中包含崩溃时的详细诊断信息。以下是常见的JVM崩溃原因及相应的解决方案。 #### 1. **内存溢出(Out of Memory)** 当JVM无法分配对象且无法通过垃圾回收释放内存时,可能导致崩溃。常见的错误包括`java.lang.OutOfMemoryError: Java heap space`和`java.lang.OutOfMemoryError: Metaspace`[^1]。 **解决方案:** - 调整JVM堆大小参数(如`-Xmx`和`-Xms`)以适应应用程序的需求。 - 使用`-XX:MaxMetaspaceSize`限制元空间大小,防止其无限增长。 - 分析内存使用情况,使用工具如VisualVM或Eclipse MAT进行内存泄漏检测。 #### 2. **Native Code问题** JVM本身是用C/C++编写的,因此与本地代码相关的错误(如JNI调用错误或JVM内部错误)可能导致崩溃。例如,访问非法内存地址或使用不兼容的本地库可能导致JVM崩溃[^1]。 **解决方案:** - 确保使用的JNI库与JVM版本兼容。 - 避免直接操作本地内存,尽量使用Java提供的API。 - 更新JVM到最新版本,以修复已知的本地代码问题。 #### 3. **JVM Bug** 某些情况下,JVM自身的实现可能存在缺陷,导致特定条件下崩溃。例如,JIT编译器在某些版本中可能存在错误,导致生成的代码引发崩溃[^1]。 **解决方案:** - 升级到最新的JVM版本,修复已知的JVM缺陷。 - 如果怀疑是JVM Bug,可以尝试更换JVM供应商(如从Oracle JDK切换到OpenJDK)。 #### 4. **线程问题** 线程死锁或线程资源耗尽可能导致JVM崩溃。例如,创建过多线程可能导致系统资源耗尽,进而引发崩溃。 **解决方案:** - 使用`-Xss`参数调整线程栈大小,避免线程占用过多内存。 - 使用线程池管理线程资源,避免无限制创建线程。 - 使用`jstack`工具分析线程状态,检测死锁或线程阻塞问题。 #### 5. **第三方库问题** 某些第三方库可能与JVM不兼容,或者存在内存泄漏问题,导致JVM崩溃。例如,某些网络库或数据库驱动可能在特定条件下引发崩溃。 **解决方案:** - 确保使用的第三方库与JVM版本兼容。 - 定期更新第三方库到最新版本,修复已知问题。 - 使用工具分析第三方库的内存使用情况,检测潜在问题。 #### 6. **系统资源不足** 系统资源不足(如CPU、内存、磁盘I/O)可能导致JVM崩溃。例如,系统内存不足时,操作系统可能终止JVM进程[^1]。 **解决方案:** - 监控系统资源使用情况,确保系统资源充足。 - 使用资源限制工具(如cgroups)控制JVM进程的资源使用。 - 在云环境中,确保实例配置足够资源以支持JVM运行。 #### 7. **JVM参数配置不当** 不当的JVM参数配置可能导致JVM崩溃。例如,设置过高的堆大小可能导致JVM无法分配内存,进而引发崩溃[^1]。 **解决方案:** - 合理配置JVM参数,确保参数与系统资源匹配。 - 使用JVM参数分析工具(如JVM Options Analyzer)优化参数配置。 - 参考官方文档,确保参数配置符合最佳实践。 ### 日志分析与诊断工具 JVM崩溃时通常会生成`hs_err_pid`日志文件,该文件包含崩溃时的详细诊断信息。可以通过分析该日志文件定位崩溃原因。 **常用诊断工具:** - `jstack`:用于分析线程状态,检测线程死锁或阻塞问题。 - `jmap`:用于生成堆转储文件,分析内存使用情况。 - `VisualVM`:提供图形化界面,支持内存、线程和性能分析。 - `Eclipse MAT`:用于分析堆转储文件,检测内存泄漏问题。 ### 示例:使用`jstack`分析线程问题 ```bash jstack <pid> > thread_dump.txt ``` 通过分析`thread_dump.txt`文件,可以检测线程死锁或阻塞问题。 ### 示例:使用`jmap`生成堆转储文件 ```bash jmap -dump:live,format=b,file=heap_dump.hprof <pid> ``` 生成的`heap_dump.hprof`文件可以使用VisualVM或Eclipse MAT进行分析。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值