【问题标题】:Running apps containing large amount of code运行包含大量代码的应用程序
【发布时间】:2014-02-19 10:52:37
【问题描述】:

背景

似乎一些旧的 Android 操作系统(甚至可能是最新的)对每个应用程序可以容纳的代码量有限制。

正如我所发现的,限制是在一个名为 "LinearAlloc" 的缓冲区上。

在 2.2 或 2.3 上大约为 5-8 MB,我认为在其他版本上为 16 或更多。

问题

如果您的代码过大(并且应用程序可以达到此状态),您将无法在旧设备上安装该应用程序,并出现下一个错误(也报告了here):

Installation error: INSTALL_FAILED_DEXOPT
Please check logcat output for more details.
Launch canceled!

我发现了什么

一种解决方案是尽可能多地删除代码和库,但在一些大型项目中,这样的事情很难做到。

我发现下一个链接讨论了 Facebook 如何通过某种方式提高限制来解决这个问题:

另外,谷歌已经发布了如何通过动态加载代码来解决它:

http://android-developers.blogspot.co.il/2011/07/custom-class-loading-in-dalvik.html

问题

Facebook 是如何做到的?

是否也可以通过其他方式克服这个问题?

是否有任何免费库可以增加/消除此缓冲区的限制?

对较新的 Android 版本有什么限制(如果有的话)?

其他大型应用(和游戏)如何处理这个问题?他们是否将代码放入 C/C++ 中?

动态加载 dex 文件会解决这个问题吗?

【问题讨论】:

  • 据我了解,FB 人员使用 Android 2.2 和 2.3 将不再更改的事实,因此如果您看到 2.x,您可以或多或少安全地假设您知道它的来源建于。据我了解,他们使用 JNIEnv* 传递给每个 JNI 函数来找出缓冲区地址。您必须阅读 VM 源代码才能了解他们在做什么。您可以通过将应用程序拆分为多个进程来做某事(以 IPC 为代价)。至少,两个进程应该使用两个不同的虚拟机。但是我自己并没有因为代码量限制的问题尝试这个。
  • @18446744073709551615 是的,那里有很多我听不懂的词,我认为它们来自 Android 源代码(也可能是本机代码)。但是,我认为文章所说的是,FB 以某种方式设法增加了这一限制。所以我想知道他们是如何做到的,以及是否有其他人找到的简单方法。我也想知道改变这个值是否被认为是一种黑客行为,以及它是否适用于较新的 android 版本。
  • 较新的版本 -- 不,你必须分别破解(是的)每个版本。我猜他们对新版本没有问题。至于“如何”——您在源中找到(指向)该缓冲区并了解它是如何分配的;您将了解如何通过 JNIEnv* 找到该指针;您分配所需的内存量并(!!!)将地址存储到该指针中。可能您可以执行 realloc() (如果确实重复发生,就地调整大小将是理想的)。而且您必须学习如何在应用程序终止时释放内存(OTOH,进程结束时会清除泄漏)。
  • 你是在理论上讲这些,还是你真的有什么东西可以做到?如果你做到了,你能分享你的代码/项目吗?还有,为什么会漏水?这些是应用程序使用的库...
  • 这是一个理论演讲,来自将大量预先存在的 C/C++ 代码移植到 Android 的人。我自己并没有入侵虚拟机,但我在实践中使用了单独的进程来解决一些非常老的 C/C++ 库中的内存泄漏问题。以及为什么会泄漏——如果您用自己的系统缓冲区替换系统缓冲区,那么您非常接近内存泄漏。 (PS 再次关于泄漏:为什么没有泄漏?你真的相信你已经修复了最后一个错误?

标签: android facebook dexopt


【解决方案1】:

限制是方法引用的总数:

在什么都不做和 FB/Google 文章中描述的多 dex 方法之间的中间立场是使用 ProGuard 之类的工具在 Java 级别删除对未使用代码的引用。见:

【讨论】:

  • 最小化代码不是一个解决方案,因为当您达到一定数量的代码时它对您没有帮助,而且无论如何它已经被使用了...... :(
【解决方案2】:

Google 提供了一个新的解决方案:

看来您所要做的就是接下来的任何事情: - 从“MultiDexApplication”而不是“Application”扩展 - 在应用程序的 attachBaseContext 中调用 MultiDex.install(context)

但现在我想知道:

  1. 真的是这样吗?
  2. 有什么问题吗?会影响性能吗?
  3. 它是如何工作的?
  4. 应该对 ContentProvider 做什么,因为它在应用程序初始化之前被调用?
  5. 帖子说“在所有 API 4+ 设备上为您提供 MultiDex 支持(嗯,直到 v21,您可以在本地获得此功能)”。这是否意味着从 v21 开始它将是默认行为,或者只是该类将被内置并且您不需要使用支持库的类?
  6. 此解决方案是否也适用于 Eclipse?

【讨论】:

  • 所有 Android 组件(其中包括 ContentProviders)都应该放在你的主 dex 文件中。我写了一篇文章总结(并希望回答你的其他问题)这个主题:blog.osom.info/2014/10/…
  • @AlexLipov 还没有阅读,但这看起来有很多文字和步骤,因为 Google 这么快就写了一些东西。它有效吗?它甚至可以在 Eclipse 上运行吗?
  • @android_developer 根据我的经验,它运行良好。 maven-android-plugin 支持多 dex。
  • @AlexLipov 谢谢。希望谷歌能正式推出它,让它更容易使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 2015-07-11
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多