【问题标题】:Android Libgdx Memory LeakAndroid Libgdx 内存泄漏
【发布时间】:2015-07-20 03:03:09
【问题描述】:

我正在使用 libgdx 和 android studio 制作游戏。我对这些事情的经验都相对较少。我相信我在某个地方出现了由图形引起的内存泄漏,但我不确定 libgdx 保留了大量的堆空间。 MAT 分析表明:

The class "android.content.res.Resources", loaded by "<system class loader>", occupies 17,790,184 (31.63%) bytes. The memory is accumulated in one instance of "android.util.LongSparseArray[]" loaded by "<system class loader>".

19 instances of "java.lang.reflect.ArtMethod[]", loaded by "<system class loader>" occupy 11,902,776 (21.16%) bytes. 

Biggest instances:
•java.lang.reflect.ArtMethod[64707] @ 0x70b7e4b0 - 3,894,624 (6.92%) bytes. 
•java.lang.reflect.ArtMethod[52675] @ 0x70be6888 - 3,061,192 (5.44%) bytes. 
•java.lang.reflect.ArtMethod[21833] @ 0x70000ac0 - 1,336,112 (2.38%) bytes. 
•java.lang.reflect.ArtMethod[14651] @ 0x771d2d60 - 966,680 (1.72%) bytes. 
•java.lang.reflect.ArtMethod[11453] @ 0x71f964e0 - 806,432 (1.43%) bytes. 
•java.lang.reflect.ArtMethod[11047] @ 0x709b39d8 - 662,680 (1.18%) bytes. 

205 instances of "android.graphics.NinePatch", loaded by "<system class loader>" occupy 10,041,968 (17.86%) bytes. These instances are referenced from one instance of "java.lang.Object[]", loaded by "<system class loader>"

Keywords
java.lang.Object[]
android.graphics.NinePatch

32 instances of "java.lang.DexCache", loaded by "<system class loader>" occupy 6,358,016 (11.31%) bytes. 

Biggest instances:
•java.lang.DexCache @ 0x70b50608 - 1,262,528 (2.24%) bytes. 
•java.lang.DexCache @ 0x71d2f870 - 1,177,232 (2.09%) bytes. 
•java.lang.DexCache @ 0x70bc4b60 - 903,320 (1.61%) bytes. 
•java.lang.DexCache @ 0x72178f80 - 636,768 (1.13%) bytes. 
•java.lang.DexCache @ 0x723d13f0 - 633,088 (1.13%) bytes. 

如果需要我的代码,我可以提供,但我不确定要提供哪个部分,因为我不确定泄漏在哪里。我非常感谢任何建议

【问题讨论】:

    标签: java android memory-leaks libgdx heap-memory


    【解决方案1】:

    GC 行为随着 GC 策略而改变,例如,如果策略是为了最大吞吐量,那么 JVM 将分配对象直到达到 Xmx。当它达到阈值时,GC 将启动以清除死对象。如果 GC 策略是减少暂停时间 a)Scavenge GC 和 b) Global Gc 发生直到 Global GC 发生,我们无法确保 Dead 对象是否被清除。

    最好在 OOM 上收集日志,这意味着 GC 会尽可能多地尝试清除死对象,然后 JVM 会抛出 OOM 错误。如果此时在堆转储上运行 MAT,则可以适当地找到泄漏嫌疑人。

    有关谁持有泄漏对象的强引用的更多信息,请像这样编写 OQL select * from "packagename.classname" 执行后右键单击对象-> GC 根的路径-> 排除软/弱/幻影参考。执行此操作时,MAT 将提供有关谁仍然持有引用的信息,因为 GC 没有清除对象。

    【讨论】:

    • 详细的 gc 日志也有助于识别泄漏。
    • GCMV 上的详细日志有助于识别分配模式,但可以通过 heapdump 并使用上述机制找到真正的嫌疑人。