我已阅读有关性能设计的 Android 开发人员指南。
我只是想知道,如果我有一个大对象,我无法避免创建(这很昂贵),当我知道我已经完成它时,我想立即释放它似乎是合乎逻辑的。
似乎没有办法做到这一点。
有人建议将它设置为 null 以便系统立即进行 GC,这真的是“立即”吗?因为如果系统(Dalvik VM)可以选择不释放我刚刚设置为 null 的大对象,那么将其设置为 null 根本不是解决方案。
将其设置为 null 会鼓励和加速 GC 是否正确?
这种方法是否是优化应用程序性能的“足够好”的方法?或者是否值得付出额外的努力(如果可能的话),在适用的情况下强制 GC 以从任何 Android 设备中获得最佳性能?
最佳答案
我认为您不必担心执行 GC 时的细节,因为我们无法控制何时调用 gc。即使调用 gc() 也不能保证收集。根据 System.gc() 中的文档
Indicates to the virtual machine that it would be a good time to run the garbage collector. Note that this is a hint only. There is no guarantee that the garbage collector will actually be run.
在开发具有大对象分配的应用程序时,我会担心以下问题:
- 分配大对象并随后退出该对象的生命周期范围后,我是否看到它在后面的 Activity 中被 GC 回收?这可以通过使用 adb shell 运行 dumpsys meminfo 轻松检查。您基本上会在释放内存后检查内存是否已正确进行垃圾回收,通常表示为大峰值并随后下降
- 检查这个大对象是否有明确的 GC 路径。您可以通过转储 hprof 检查此对象的引用路径并在内存分析器中检查它来执行此操作。如果是这样,你是安全的,因为 GC 会足够聪明地收集。
- 分配这个大对象后,我的堆中是否有足够的填充来执行后续 Activity ?如果对象太大,GC 可能无法足够快地收集它(这实际上与您的观点有关)并且后续 Activity 的内存消耗与先前 Activity 的剩余内存消耗实际上可能会导致内存错误。使用明确的 GC 路径设置 null 将有助于确保此对象将得到适当的 GC。我承认这是一个问题,但我的观点是,如果这成为一个问题,我们可能不得不重新审视这个特定部分的设计方式,看看我们是否可以对其进行任何优化。
- 根据需要通过 onDestroy 对 Activity 进行清理,并确保 Activity 未被其他人引用,以便它能够得到正确的垃圾收集。例如:我们经常传递 Activity 上下文而忘记它会保存它的引用。在位图上调用 recycle() 之类的事情也应该有所帮助。记住这些要点应该有助于在发生#3 的情况下准备更多空间
关于Android 手动释放对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7170042/