Android堆碎片整理策略?

7
我有一个OpenGL Android应用程序,它使用大量内存来设置一个复杂的场景,这显然导致了重大的堆碎片。即使没有内存泄漏,也无法在不因碎片而耗尽内存的情况下销毁和创建应用程序。(碎片化肯定是问题,而不是泄漏)
由于Android有一个习惯,在同一VM/堆上销毁和创建活动,这显然会导致活动崩溃。为了对抗这个问题,我使用了以下技术策略:
@Override
protected void onStop() {
    super.onStop();
    if(isFinishing()) {
        System.runFinalizersOnExit(true);
        System.exit(0);
    }
}

这确保了当活动结束时,它会导致完整的虚拟机关闭,因此下次启动活动时,它将获得一个新的未分段堆。
注意:我意识到这不是“Android方式”,但考虑到垃圾回收器是非压缩的,因此无法持续重复使用堆。
这种技术通常确实有效,但当活动以非完成模式被销毁然后重新创建时,它就无效了。
有人有关于如何处理堆退化的好建议吗?
进一步说明:减少内存消耗也不是一个真正的选项。活动实际上并没有使用那么多内存,但堆(和本地堆)似乎很容易被分段,可能是由于一些较大的内存块。

我曾经遇到同样的问题,采用了类似的解决方案。真是太糟糕了。 - Jeffrey Blattman
1个回答

4
碎片化几乎总是由于不良的分配模式而导致的结果。通常会创建和销毁大型对象,与较小的对象一起持续存在(或至少具有不同的生命周期)- 堆中会出现空洞。
在这种情况下,唯一有效的防止碎片化的方法是:防止特定的分配模式。这通常可以通过对大型对象进行汇集来实现。如果成功,则应用程序将以更好的执行速度感激这一点。
@编辑:针对您的问题,如果应用程序重新启动后堆仍未为空,则堆上还有什么要保留的内容?您确认这不是内存泄漏的问题,但是它似乎就是。由于您正在使用OpenGL - 可能是因为OpenGL资源没有正确被处理,所以一些本地包装器仍然存在吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接