经验 | 向AOSP贡献虚拟机的优化
内容提要
这篇文章介绍了作者向AOSP贡献的一项优化改动,用于改进JNI调用的功能。作者详细记录了整个开发过程中遇到的问题和经验,并对改动的影响进行了测算。最后,作者提到了一些与国内App生态相关的注意事项。
延伸解读
优化原理与受益范围
文章指出,JNI跳板函数的生成仅取决于参数类型和标志,因此多个native方法可共用同一个JNI stub。作者利用这一特性,让App中85%~90%的Java native方法能够复用boot images中已编译的JNI stub,从而减少JIT编译开销。这一优化已合入ART主线,将在Android 15中发布,涉及20个文件和1155行代码。
性能影响:微观显著,宏观有限
作者从四个维度测算优化效果:覆盖面上,国内top10应用的native方法有85%~90%可受益;调用耗时上,50000次addOne调用从3919.2秒降至1065.3秒,提升约267%;AOT编译时间改进1%~2%;odex文件大小变化微弱。但应用启动等宏观场景提升不明显,可能因JNI调用占比低。因此,该优化对JNI调用密集场景收益更显著。
开发经验:测试先行与代码质量
作者反思开发过程,认为最大教训是测试代码写得太晚。由于优化涉及不同架构的hash和equal策略,细微错误可能导致方法错误共用stub,引发难调试的问题。若提前编写GTest测试,可更早暴露问题。此外,Google工程师在review中提出30多条关于性能和代码整洁的建议,强调正确性只是第一步,代码写法同样关键。
对国内App生态的潜在影响
文章提到,国内App常用的hook方案可能受影响:若修改Java方法生成的机器码,由于机器码可能被复用,会波及多个方法。同时,Android 15将art/runtime下的namespace全部隐藏,导致许多符号不再导出,依赖这些符号篡改虚拟机行为的App需调整解析方式。虽然符号仍存于.gnu_debugdata段,但Google警告,依赖调试数据绕过限制可能导致每次大版本更新后崩溃。
Q&A
这项JNI调用的优化改动对哪些Java native方法有影响?
这项优化预计使85%~90%的Java native方法受益。
作者在开发过程中遇到了哪些主要困难?
作者在开发过程中遇到了许多bug,强调了早期编写测试代码的重要性。
如何简化ART模块的下载和更新流程?
通过APEX机制,ART模块的下载和更新流程得以简化。
优化后的JNI调用性能提升有多大?
在50000次调用中,优化后的JNI调用时长从3919.2秒降至1065.3秒,提升了267%。
作者在代码提交过程中遇到了哪些反馈?
Google工程师提出了关于性能和代码整洁的建议,强调代码质量的重要性。
这项优化对国内App生态有什么潜在影响?
优化可能影响国内App的hook计划,特别是对Java方法生成的机器码的修改。