Android 2.3 DEX/LinearAllocHdr超限 INSTALL_FAILED_DEXOPT

注:转自如下网址。个人不太喜欢该VM限制的方法,所以都是跑跑脚本,看哪里方法数与功能数不成正比就想办法删一删,引用了jar的如果可以引用源代码就改成用源代码然后删掉不需要的功能。


http://viila.info/2014/04/android-2-3-dex-max-function-problem/


当安卓工程庞大到一定程度(代码结构渣到一定程度)的时候,就会遇到诸如最大方法数超过限制导致无法安装,Crash等问题。

相关关键词:Android 2.3 INSTALL_FAILED_DEXOPT 65535

问题的本质有两个

  • dx打包时限制了单个dx文件的最大方法数为65535
  • Dalvik VM限制内存中加载的方法数(方法,类定义及构造函数)不能超过65535个

问题的重现很简单

  • 写一个类,把函数复制个6w份,一build,报错
  • apk安装到2.3系统,提示INSTALL_FAIL_DEXOPT
  • 动态加载两个DEX模块,每个函数3w份,一加载运行,程序Crash

网上一般推荐的解决方法

  • 删代码以及jar包,尤其是自动生成的get/set,没用的类,可以使用proguard自动优化掉无用代码
  • 由于高于Gingerbread的版本将LinearAllocHdr分配空间从5M提高到8M,放弃2.3的用户后可以有一定的缓冲时间
  • 使用dex动态加载的方式将程序内的模块插件化,这样会将问题1转化为问题2,如果程序加载项过大时还是会有崩溃现象出现
  • 将java层逻辑移到jni层实现
  • hacking dalvik vm

Facebook曾经遇到了这样的问题,有一个相关博文(Under the Hood: Dalvik patch for Facebook for Android),一通碎碎念后大概解决方法是发了一个lite版本去掉了一大票功能,以及写了一个小补丁hack掉Android Dalvik VM把它搞大了。。。

hacking dalvik vm的方法似乎是最干净利落的。可惜facebook语焉不详,参照博文中给出的信息,可以找到LinearAllocHdr*指针位于vm/Globals.h

使用jni写了个小程序做了以下几件事情实现了该hacking

  1. 通过jni方法取到*env
  2. 指针往回便利内存查找65535对应内存块
  3. 重新mmap8M内存,替换到len以及Hdr的当前位置到新map的位置

代码回头再放到github。

另外提供一个小工具可以用来反编译apk以统计构建出来的apk内*大约*有多少个方法
小工具里面会依据文件名缓存先前反编译的结果,可以用-diff参数将两个版本apk对比,查看具体到包的方法数变动


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值