一、背景
R8作为谷歌官方的编译优化工具,在编译阶段会对字节码进行大规模修改,以追求包体优化和性能提升。但是Android应用开发者数量太过庞大,无论测试流程多么完善,终究难以避免在一些特定场景下出现问题。
近期我们在升级项目的AGP,遇到了一个指向系统SurfaceTexture类的native崩溃问题。经反编译分析发现问题最终指向了smali字节码中多余的一行new-instance指令。
该指令创建了一个SurfaceTexture对象,但是并未调用其
二、复现问题
我们注意到多出来的new-instance指令下面紧接着的是对a0.e 类中的静态方法 i() 的调用,其内部实现就是SurfaceTexture的构造方法。这是典型的代码外联操作,即一段相同的代码在工程中多次出现,则会被抽出来单独作为一个静态函数,原先的调用点则替换成该函数的调用,这样可以减小代码体积,是常见的编码思路。
例如:
class Activity{
void onCreate(){
// ...
String a = xx.xxx();
String b = xx.xxx();
Log.e("log",a+b);
//...
}
void onReusme(){
// ...
String a = xx.xxx();
String b = xx.xxx();
Log.e("log",a+b);
//...
}
}
class Activity{
void onCreate(){
// ...
Activity$Outline.log();
//...
}
void onReusme(){
// ...
Activity$Outline.log();
//...
}
}
//外联生成的类
class Activity$Outline{
public static void log(){
String a = xx.xxx();
String b = xx.xxx();
Log.e("log",a+b);
}
}
我们根据这个生成类的类名可以知道是R8中ApiModelOutline功能生成了这个类。
我们进到R8工程中检索下相关的关键字,再加上demo多次尝试,可以确认满足以下条件能够必现该问题:
- 使用了高于当前minSdkVersion的系统函数/变量(仅限系统类,自己写的无效)
- 用synchronized或者try语句块包裹了该调用,或者给该函数传参时有任何计算行为(除了传局部变量)。例如:
- new SurfaceTexture( getParmas() )
- new SurfaceTexture( if(enable) 1 : 2)
- new SurfaceTexture ( (boolean) enable )
未经允许不得转载:紫竹林-程序员中文网 » R8疑难杂症分析实战:外联优化设计缺陷引起的崩溃|得物技术
相关推荐
- 企业AI支出失控?NJET AI网关帮您守住预算红线
- 社区项目ROSA-Tuning:验证RWKV-8 ROSA效果
- 使用 Elastic Agent Builder 和 MCP 实现 Agentic 参考架构
- LinkedIn 验证码解决方案
- SpreadJS V19.0 新特性解密:单元格两端对齐,重塑表格排版美学与专业度 | 葡萄城技术团队
- SpreadJS V19.0 新特性解密:WebWorker 驱动的增量计算,让海量数据表格运算快如闪电 | 葡萄城技术团队
- 为什么有些项目干着干着就成紧急项目了? 原 荐
- Anolis OS 23.4 发布:全面支持 RVA23 RISC-V 架构,强化安全与云原生生态 原 荐