Hello!
我是一名 Java 和 Android 开发新手,最近在处理应用程序的内存管理方面遇到了麻烦。我将把本文分成几个部分,以使其更清晰易读。
我的应用程序的简要说明
这是一个由多个阶段(级别)组成的游戏。每个阶段都有一个玩家的起点和一个出口,引导玩家进入下一个阶段。每个阶段都有自己的一组障碍。目前,当玩家到达最后阶段(到目前为止我只创建了 4 个阶段)时,他/她会自动返回到第一阶段(1 级)。
一个名为的抽象类游戏对象(延伸Android.View)定义了玩家以及游戏中存在的所有其他对象(障碍物等)的基本结构和行为。所有对象(本质上是视图)都在我创建的自定义视图中绘制(扩展了 FrameLayout)。游戏逻辑和游戏循环由副线程(gameThread)处理。这些阶段是通过从 xml 文件检索元数据来创建的。
问题
除了我的代码中所有可能的内存泄漏(所有这些我一直在努力寻找和解决)之外,还有一个与垃圾收集器相关的奇怪现象发生。我不会用文字来描述它,以免让你感到困惑,而是使用图像。正如孔子所说:“形象胜千言”。好吧,在这种情况下,我刚刚让您免于阅读 150,000 个单词,因为下面我的 GIF 有 150 帧。
描述:第一个图像代表首次加载“第一阶段”时我的应用程序的内存使用情况。第二张图片 (GIF) 首先代表第二次加载“第一阶段”时我的应用程序的内存使用时间线(如前所述,当玩家击败最后一个阶段时会发生这种情况),然后是四个垃圾收集是我强行发起的。
您可能已经注意到,两种情况之间的内存使用量存在巨大差异(几乎 50MB)。首次加载“Stage 1”时,游戏启动时,应用程序使用 85MB 内存。当第二次加载同一个stage时,稍晚一点,内存使用量已经是130MB了!这可能是由于我的编码不当造成的,因此我不在这里。您是否注意到,在我强制执行 2 次(实际上是 4 次,但只有前 2 次重要)垃圾回收后,内存使用量又回到了“正常状态”(与首次加载阶段时的内存使用量相同)?这就是我说的奇怪现象.
问题
If the 垃圾收集器应该从内存中删除不再被引用的对象(或者至少只有弱引用), 为什么你上面看到的“垃圾内存”只有当我强行调用时才会被删除GC并且不在GC's正常处决?我的意思是,如果垃圾收集我手动启动可以消除这个“thrash”,然后正常GC's处决也能够将其删除。为什么它没有发生?
我什至尝试过打电话系统.gc()当阶段被切换时,但是,即使垃圾收集发生这种情况时,这个“thrash”内存不会像我手动执行时那样被删除GC。我是否遗漏了一些关于如何垃圾收集器工作原理或者 Android 如何实现它?
最后的考虑因素
我花了几天时间搜索、研究和修改我的代码,但我无法找出为什么会发生这种情况。 StackOverflow 是我最后的手段。谢谢你!
NOTE:我本来打算发布我的应用程序源代码的一些可能相关的部分,但由于问题已经太长了,我将在此停止。如果您觉得需要检查一些代码,请告诉我,我将编辑这个问题。
我已经读过的内容:
Java中如何强制垃圾回收? https://stackoverflow.com/questions/1481178/how-to-force-garbage-collection-in-java
Android 中的垃圾收集器 https://stackoverflow.com/questions/3117429/garbage-collector-in-android
Oracle 的 Java 垃圾收集基础知识 https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
Android 内存概述 https://developer.android.com/topic/performance/memory-overview
Android 中的内存泄漏模式 https://android.jlelse.eu/memory-leak-patterns-in-android-4741a7fcb570
避免 Android 中的内存泄漏 https://android-developers.googleblog.com/2009/01/avoiding-memory-leaks.html
管理应用程序的内存 https://developer.android.com/topic/performance/memory
关于 Android 应用程序内存泄漏您需要了解的内容 https://techbeacon.com/what-you-need-know-about-android-app-memory-leaks
使用 Memory Profiler 查看 Java 堆和内存分配 https://developer.android.com/studio/profile/memory-profiler
LeakCanary(适用于 Android 和 Java 的内存泄漏检测库) https://github.com/square/leakcanary
Android 内存泄漏和垃圾收集 https://stackoverflow.com/questions/31635184/android-memory-leak-and-garbage-collection
通用 Android 垃圾收集 https://stackoverflow.com/questions/11035593/generic-android-garbage-collection
如何从内存中清除动态创建的视图? https://stackoverflow.com/questions/9949047/how-to-clear-dynamically-created-view-from-memory
引用在 Android 和 Java 中如何工作 https://medium.com/google-developer-experts/finally-understanding-how-references-work-in-android-and-java-26a0d9c92f83
Java 垃圾收集器 - 未定期正常运行 https://stackoverflow.com/questions/4309105/java-garbage-collector-not-running-normally-at-regular-intervals
android 中的垃圾收集(手动完成) https://stackoverflow.com/questions/8177802/garbage-collection-in-android-done-manually
...还有更多我找不到了。