1

这是一个普遍的问题。在我的应用程序中,垃圾收集器运行得太频繁(每秒几次)并且没有释放大量内存(小于 1Mb)。问题是,堆大小不再增长。它需要大约 40Mb,有时在其他手机上需要 60Mb,其中应用程序的最大值为 128Mb (Galaxy S4) 或 196Mb (Nexus 4)。

为什么 GC 运行如此频繁?

下面是 GC 运行太频繁时 logcat 的一部分。申请被冻结。我什至什么都不做,我只是尝试缩放地图。

06-07 16:50:52.003: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60015K/72980K, paused 51ms, total 51ms
06-07 16:50:52.053: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60016K/72980K, paused 51ms, total 51ms
06-07 16:50:52.113: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60016K/72980K, paused 52ms, total 52ms
06-07 16:50:52.163: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60017K/72980K, paused 52ms, total 52ms
06-07 16:50:52.213: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60017K/72980K, paused 51ms, total 52ms
06-07 16:50:52.273: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60018K/72980K, paused 51ms, total 51ms
06-07 16:50:52.324: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60018K/72980K, paused 51ms, total 51ms
06-07 16:50:52.374: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60019K/72980K, paused 52ms, total 52ms
06-07 16:50:52.434: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60019K/72980K, paused 53ms, total 53ms
06-07 16:50:52.484: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60020K/72980K, paused 52ms, total 52ms
06-07 16:50:52.544: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60020K/72980K, paused 56ms, total 56ms
06-07 16:50:52.594: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60021K/72980K, paused 52ms, total 52ms
06-07 16:50:52.654: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60021K/72980K, paused 52ms, total 52ms
06-07 16:50:52.704: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60022K/72980K, paused 52ms, total 52ms
06-07 16:50:52.754: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60022K/72980K, paused 52ms, total 52ms
06-07 16:50:52.814: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60023K/72980K, paused 52ms, total 52ms
06-07 16:50:52.864: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 6023K/72980K, paused 51ms, total 51ms
06-07 16:50:52.924: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60024K/72980K, paused 55ms, total 56ms
06-07 16:50:52.974: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60024K/72980K, paused 52ms, total 52ms
06-07 16:50:53.024: D/dalvikvm(26176): GC_FOR_ALLOC freed 256K, 18% free 60025K/72980K, paused 52ms, total 52ms
4

3 回答 3

3

您的问题与 Google Maps Android API 的工作方式以及您的应用程序分配了多少内存有关。

40-60 MB 可能有问题,因为执行单个 GCollection 需要更长的时间。作为旁注:我注意到添加 1000 个标记需要更长的时间,当分配 15 MB 时与分配到 5 MB 时相比。

除此之外,对 Google Play 服务 API 的每次调用都在执行 IPC,这反过来又根据这个 answer强制 GC 。平移或缩放时可能会执行此类 IPC 调用。

最好将内存占用保持得更低。

于 2013-06-07T20:46:05.370 回答
0

GC 在需要时运行。一般来说,(即使在 DVM 上)它确实比您更清楚地知道何时需要运行。如果您将此问题不是 GC 的问题,而是您的应用程序内存的问题,它可能会帮助您找到解决方案。

频繁 GC 最可能的原因是您的内存快用完了。例如,如果您分配大量短期对象,则可能会发生这种情况:您快速分配它们,但很快忘记它们。每次 GC 运行时,它都会成功恢复足够的内存以供应用程序继续运行……但同样快,您会再次填充内存。

如果这确实是正在发生的事情,那么,如果你有更多的内存,正如@parry 所建议的那样,你只会延迟问题。GC 发生的频率会降低,但运行时间会更长(因为它们会收集更多垃圾)。这可能就足够了,但可能还不够。

检查您是否在经常调用的例程中分配对象(例如,您的绘图例程)。

于 2013-06-07T15:58:41.407 回答
-3

如果您认为 GC 表现得很愚蠢(很可能),并且 VM 有更多内存可用,那么您可以尝试通过要求一次性 1/5/10 MB 分配来强制它增加堆大小(保护它带有 OOME 的 try-catch)。这可能会导致 GC 在每个循环中清理更多,或增加发生完整 GC 的机会。
另一个适用于 PC 的启发式方法是在循环中调用 System.GC() x 次以触发完整的 GC。
总而言之,我自己也遇到过,很糟糕。

于 2013-11-03T22:40:41.740 回答