【发布时间】: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://www.slashgear.com/how-facebook-fixed-its-gingerbread-dalvik-problem-04272478/
- http://arstechnica.com/business/2013/03/how-facebook-dug-deep-within-android-to-fix-its-mobile-app/
- https://www.facebook.com/notes/facebook-engineering/under-the-hood-dalvik-patch-for-facebook-for-android/10151345597798920
另外,谷歌已经发布了如何通过动态加载代码来解决它:
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 再次关于泄漏:为什么没有泄漏?你真的相信你已经修复了最后一个错误?)