【问题标题】:Why does the Garbage Collector runs without reaching max heap limit?为什么垃圾收集器在没有达到最大堆限制的情况下运行?
【发布时间】:2015-04-09 07:48:45
【问题描述】:

我正在开发一个实时应用程序。为了解决非线性优化问题,我集成了 Java 求解器 jcobyla (https://github.com/cureos/jcobyla)。每次求解器运行时,垃圾收集器都会在大量运行时进行大量工作:

02-09 12:58:16.822: V/onCreate(7061): maxMemory:512524288k

02-09 13:04:23.127: D/dalvikvm(7061): GC_FOR_ALLOC freed 10314K, 40% free 17304K/28544K, paused 16ms, total 16ms   

02-09 13:04:23.177: D/dalvikvm(7061): GC_FOR_ALLOC freed 3437K, 34% free 17304K/26196K, paused 11ms, total 11ms

02-09 13:04:23.222: D/dalvikvm(7061): GC_FOR_ALLOC freed 3437K, 34% free 17304K/26196K, paused 10ms, total 10ms

02-09 13:04:23.322: D/dalvikvm(7061): GC_FOR_ALLOC freed 10304K, 33% free 17303K/25452K, paused 18ms, total 18ms

>02-09 13:04:23.367: D/dalvikvm(7061): GC_FOR_ALLOC freed 3437K, 33% free 17303K/25452K, paused 11ms, total 11ms

02-09 13:04:23.417: D/dalvikvm(7061): GC_FOR_ALLOC freed 3437K, 33% free 17303K/25452K, paused 12ms, total 12ms

02-09 13:04:23.522: D/dalvikvm(7061): GC_FOR_ALLOC freed 10304K, 40% free 17304K/28540K, paused 16ms, total 17ms

02-09 13:04:23.567: D/dalvikvm(7061): GC_FOR_ALLOC freed 3437K, 34% free 17304K/26196K, paused 11ms, total 11ms

02-09 13:04:23.612: D/dalvikvm(7061): GC_FOR_ALLOC freed 3437K, 34% free 17304K/26196K, paused 11ms, total 11ms 

我尝试了很多方法来阻止 GC 运行。相信求解器达到了我使用的应用程序的最大堆限制android:largeHeap="true"。在单独的进程中运行求解器也没有解决问题。

正如您在上面的 LogTag 中看到的,应用程序的最大堆限制约为 512MB,这对于 jcobyla 来说绰绰有余(大约需要 300MB)。运行后 GC 告诉我有 34% 的空闲空间为 24.85 MB。运行 jcobyla 时应用程序的总 RAM 使用量约为 20 MB。

为什么 GC 显示的限制与应用的最大堆限制不同?

如何增加求解器可能的内存使用量?

如何防止 GC 运行?

【问题讨论】:

    标签: android memory-leaks garbage-collection


    【解决方案1】:

    每次求解器运行垃圾收集器时,都会使用大量运行时间进行大量工作

    GC_FOR_ALLOC 表示如果没有一轮 GC 并可能扩展堆,您分配内存的请求将无法满足。

    对于 jcobyla 来说已经足够了(大约需要 300MB)

    我不知道您是如何确定的,尤其是对于 Android。此外,您自己的分析声称情况并非如此,否则您的堆至少会增长到 300MB,但它并没有这样做。

    为什么 GC 显示的限制与应用的最大堆限制不同?

    因为堆还没有增长到极限。目标是最小化进程的系统 RAM 占用。进程越大,Android 就越需要终止其他进程以使所有内容都适合系统 RAM。这会损害用户体验,例如多任务处理。

    如何增加求解器可能的内存使用量?

    根据您的分析,您不需要为求解器增加可能的内存使用量。

    如何防止 GC 运行?

    停止使用使用 GC 的编程语言,或停止为 Android 编程并切换到某些桌面操作系统。

    您的应用是众多适用于 Android 的应用之一,它也是任何给定 Android 设备上的众多应用之一。 Android 设备的系统 RAM 可能非常少——例如,Android One 设备可能只有 512MB 的 RAM。这适用于操作系统和所有正在运行的应用程序进程,而不仅仅是您。 Android,尤其是 Dalvik/ART,是围绕协作模型构建的,其中每个进程都试图最小化其内存消耗。

    但是:

    • 如果您使用 NDK 以 C/C++ 编写应用程序,不仅没有 GC,而且您没有堆限制,除了用户认为您的应用程序对其设备有害的净效应到它使用的系统 RAM 量

    • 如果您为其他操作系统编写应用程序,您将受制于该操作系统的内存管理策略,并且桌面操作系统更有可能允许您更积极地使用系统 RAM

    【讨论】:

    • @canScan,此外,Dalvik 不使用移动垃圾收集器,因此即使您有必要的可用空间来分配对象,也可能没有足够的连续可用空间,需要 GC_FOR_ALLOC。
    • 感谢您的详细解答。 @CommonsWare,内存使用量是在台式计算机上运行 jcobyla 测量的。看来 NDK 是达到我需要的性能的唯一方法。
    • @canScan:“内存使用量是在台式计算机上运行 jcobyla 测量的”——请注意,内存使用量不会相同,因为运行时不同。正如 Tanis.7x 所指出的,Dalvik does not have a compacting (or moving) garbage collector,因此您可以更轻松地对堆进行分段。一个普通的 Java 库通常不会按照 Android 应用所需的方式优化内存消耗(例如,回收现有对象而不是依赖 GC 和新分配)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-30
    • 2014-12-07
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    相关资源
    最近更新 更多