Android MultiDex、什么是64K限制和LinearAlloc限制

原文出处

64K限制

随着Android应用功能的增加,代码量不断地增大,当应用方法数量超过了65536的时候,编译的时候便会提示:


image.png

这个Android著名的Dex 64k method数量上限。那么,是什么原因导致方法数不能超过64K呢?网上搜集了一下资料,原因一般有:

  1. DexOpt优化的限制:当Android系统启动一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt。DexOpt的执行过程是在第一次加载Dex文件的时候执行的。这个过程会生成一个ODEX文件,即Optimised Dex。执行ODex的效率会比直接执行Dex文件的效率要高很多。但是在早期的Android系统中,DexOpt有一个问题,也就是这篇文章想要说明并解决的问题。DexOpt会把每一个类的方法id检索起来,存在一个链表结构里面。但是这个链表的长度是用一个short类型来保存的,导致了方法id的数目不能够超过65536个。当一个项目足够大的时候,显然这个方法数的上限是不够的。尽管在新版本的Android系统中,DexOpt修复了这个问题,但是我们仍然需要对老系统做兼容
  2. dalvik bytecode的限制:因为 Dalvik 的 invoke-kind 指令集中,method reference index 只留了 16 bits,最多能引用 65535 个方法,参考链接:http://stackoverflow.com/questions/21490382/does-the-android-art-runtime-have-the-same-method-limit-limitations-as-dalvik/21492160#21492160,http://source.android.com/devices/tech/dalvik/dalvik-bytecode.html

鉴于以上原因,在打包Android应用的时候,会对方法数做一个检测,当方法数超过了DexFormat.MAX_MEMBER_IDX(定义为0Xffff, 注意,这个不是Dex文件格式的限制,Dex文件中存储方法ID用的并不是short类型,无论最新的DexFile.h新定义的u4是uint32_t,还是老版本DexFile引用的vm/Common.h里定义的u4是uint32或者unsigned int,都不是short类型,特此说明)便报错

LinearAlloc限制

即使方法数没有超过65536,能正常编译打包成apk,在安装的时候,也有可能会提示INSTALL_FAILED_DEXOPT而导致安装失败,这个一般就是因为LinearAlloc的限制导致的。这个主要是因为Dexopt 使用 LinearAlloc 来存储应用的方法信息。Dalvik LinearAlloc 是一个固定大小的缓冲区。在Android 版本的历史上,LinearAlloc 分别经历了4M/5M/8M/16M限制。Android 2.2和2.3的缓冲区只有5MB,Android 4.x提高到了8MB 或16MB。当方法数量过多导致超出缓冲区大小时,也会造成dexopt崩溃

谷歌分包方案

谷歌提供了一个multiDex的分包方案,当方法数超过65536的时候,生成多个dex文件,把应用启动时必须用到的类和该类的直接引用类放到main dex中,把其他类放到second dex中。当应用启动之后,动态加载second dex,从而避免64k问题。使用Android Studio很容易实现分包方案:


image.png

1、在build.gradle中添加:multiDexEnabled true
2、加入依赖‘compile 'com.android.support:multidex:1.0.1'’
3、让应用的Application类直接使用或者继承MultiDexApplication
4、如果你想使用自定义的Application,又不想继承MultiDexApplication,那么可以在attachBaseContext方法里执行MultiDex.install(base)
以上就是谷歌multiDex方案所需做的设置,通过配置multiDex,便可解决64k方法数限制

谷歌multiDex存在的问题

虽然谷歌的分包方案很简单,但是效果并不是那么好,谷歌本身也枚举了分包方案的缺点:

1、如果在主线程中执行MultiDex.install,加载second dex,因为加载从dex是同步的,会阻塞线程,second dex太大的话,有可能导致ANR
2、API Level 14之前,由于Dalvik LinearAlloc bug(问题22586,就是上文提到的LinearAlloc问题),很可能会出问题的
3、应用程序使用了multiedex配置的,会造成使用比较大的内存
4、对于应用程序比较复杂的,存在较多的library的项目。multidex可能会造成不同依赖项目间的dex文件函数相互调用,找不到方法

如何解决谷歌分包方案的问题

针对上面的问题,参考网上的一些解决方案,如美团、facebook、微信等,初步使用的解决方法如下:

1、第一次启动的时候,检测到未曾加载过second dex,那么启动欢迎页面(启动新的进程,原来进程进入阻塞等待,注意,此时不会发生ANR,因为已经不是前台进程了),在欢迎页面里面进行second dex的加载,加载完成后通知主线程继续
2、设定单个dex文件最大方法数为48000(经验值)而不是65536,避免内存问题
3、同上
4、控制程序逻辑,未曾加载完second dex之前,进入阻塞等待,直到加载完程序才往下走


image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,063评论 6 510
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,805评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,403评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,110评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,130评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,877评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,533评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,429评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,947评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,078评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,204评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,894评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,546评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,086评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,195评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,519评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,198评论 2 357

推荐阅读更多精彩内容