报错日记
"org.jf.util.ExceptionWithContext: Exception occurred while writing code_item for method Activity路径;->init()V"
"\tat org.jf.dexlib2.writer.DexWriter.writeDebugAndCodeItems(DexWriter.java:825)"
"\tat org.jf.dexlib2.writer.DexWriter.writeTo(DexWriter.java:268)"
"\tat org.jf.dexlib2.writer.DexWriter.writeTo(DexWriter.java:246)"
"\tat org.jf.smali.Smali.assemble(Smali.java:130)"
"\tat com.taobao.sophix.impl.PatchCommand.start(PatchCommand.java:373)"
"\tat com.taobao.sophix.Main.main(Main.java:34)"
"Caused by: org.jf.util.ExceptionWithContext: Error while writing instruction at code offset 0x12"
"\tat org.jf.dexlib2.writer.DexWriter.writeCodeItem(DexWriter.java:1098)"
"\tat org.jf.dexlib2.writer.DexWriter.writeDebugAndCodeItems(DexWriter.java:821)"
"\t... 5 more"
"Caused by: org.jf.util.ExceptionWithContext: Unsigned short value out of range: 143796"
"\tat org.jf.dexlib2.writer.DexDataWriter.writeUshort(DexDataWriter.java:116)"
"\tat org.jf.dexlib2.writer.InstructionWriter.write(InstructionWriter.java:236)"
"\tat org.jf.dexlib2.writer.DexWriter.writeCodeItem(DexWriter.java:1025)"
"\t... 6 more"
问题排查
首先公司有两个项目:项目A和项目B,在项目A上可以正常生成补丁,但是项目B就会生成补丁失败,对比了两个项目的配制文件大部分都是一样的,自己网上搜了一下,都没有遇到过类似的问题,后面就请教阿里的工程师了,记录如下:
阿里给的回复可能是插件住代码中插入不同的代码了,导致两次编译出来的apk差别很大,项目是用到AspectJ插入代码,但是两个项目都有用到了,也排除了不是这个问题引用的
这里注意通过使用Android Studio自带的工具来对比两个apk的差别是不准的,后面使用apktool反编译apk,然后再对比两个apk的区别(这一步是关键,后面一步步分析最终找到问题所在)
反编译的apk对比如下:
这里看出虽然我只改一项目的一点代码,但是再次打包的时候资源文件也会不一样,搜了一下资源文件,发现不同的模块都用引用到相同的资源名称,所以想到就是不同的模块在合并相同资源文件的时候会导致每次合并的结果会不一样
对比每次打包出来的依赖列表,发现每次打包出来的依赖顺序都会不一样,项目是使用自己写的一个插件进行模块化管理的,代码是使用HashSet
来保存的,而HashSet是无序的,就导致读取出来的依赖列表也是无序的,改用LinkedHashSet
就解决了
总结:自己在这个问题上花好几天时间, 主要原因还是方法不对,生成补丁不成功,第一时间想着是项目配制或者是代码的问题引起的,但是当一个项目很大的时候,很难快速定位到问题,这里浪费了很多的时间,后面还是要从结束出来,生成补丁失败了,直接反编译apk看具体的差别,这个就能很快定位问题了