Hack Dalvik VM解决Android 2.3 DEX/LinearAllocHdr超限

来源:互联网 发布:手机打不开数据流量 编辑:程序博客网 时间:2024/06/05 08:17

当安卓工程庞大到一定程度(代码结构渣到一定程度)的时候,就会遇到诸如最大方法数超过限制导致无法安装,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。
https://github.com/viilaismonster/LinearAllocFix

另外提供一个小工具可以用来反编译apk以统计构建出来的apk内*大约*有多少个方法

小工具里面会依据文件名缓存先前反编译的结果,可以用-diff参数将两个版本apk对比,查看具体到包的方法数变动


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

0 0
原创粉丝点击