【问题标题】:Java GC running very frequently after minimal allocationsJava GC 在最小分配后非常频繁地运行
【发布时间】:2012-03-10 05:50:08
【问题描述】:

我正在为 android 编写一个实时游戏,因此我想尽可能减少分配/垃圾收集,如 android“为性能而设计”开发者指南中的建议。

我有一个非常简单的游戏,它使用的内存不多(根据 hprof 堆转储,

19  24  byte[]  5   dalvik.system.NativeStart   run 
18  12  java.lang.Integer   5   java.lang.Integer   valueOf 
17  24  org.apache.harmony.dalvik.ddmc.Chunk    5   org.apache.harmony.dalvik.ddmc.DdmServer    dispatch    
16  17  byte[]  5   android.ddm.DdmHandleHeap   handleREAQ  
15  24  org.apache.harmony.dalvik.ddmc.Chunk    5   android.ddm.DdmHandleHeap   handleREAQ  
14  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
13  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
12  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
11  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
10  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
9   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
8   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
7   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
6   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
5   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
4   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
3   24  byte[]  5   dalvik.system.NativeStart   run 
2   12  java.lang.Integer   5   java.lang.Integer   valueOf 
1   24  org.apache.harmony.dalvik.ddmc.Chunk    5   org.apache.harmony.dalvik.ddmc.DdmServer    dispatch    

尽管如此,我仍然每隔几秒就会看到大约 1MB 的收集:

03-09 21:41:56.665: D/dalvikvm(4210): GC_CONCURRENT freed 934K, 58% free 3069K/7175K, external 2847K/3550K, paused 3ms+2ms
03-09 21:42:03.685: D/dalvikvm(4210): GC_CONCURRENT freed 937K, 58% free 3069K/7175K, external 2847K/3550K, paused 3ms+1ms
03-09 21:42:10.705: D/dalvikvm(4210): GC_CONCURRENT freed 937K, 58% free 3069K/7175K, external 2847K/3550K, paused 5ms+2ms
03-09 21:42:17.715: D/dalvikvm(4210): GC_CONCURRENT freed 934K, 58% free 3069K/7175K, external 2847K/3550K, paused 3ms+1ms
03-09 21:42:24.725: D/dalvikvm(4210): GC_CONCURRENT freed 934K, 58% free 3069K/7175K, external 2847K/3550K, paused 2ms+3ms

我知道时间不多,但如果可以避免的话,我不希望从我的一个帧中随机偷走 10 毫秒。我的问题是,如果我在分配跟踪器中看不到任何内容,那么是什么在短短几秒钟内分配了这么多内存?我不认为手机背景上有任何东西,因为我一退出游戏就再也看不到 GC(或很少看到)。

我的渲染线程使用 GLSurfaceView,这几乎是它暂停时唯一运行的东西,但我只是不知道我的记忆要去哪里。

感谢任何想法。

【问题讨论】:

  • 你在使用迭代器吗?根据 JVM 构造的版本,例如 Object in Collection 可能会生成需要 GC 的对象。
  • @RussS 我曾经在 foreach 循环中经常使用它们,但为了解决这个问题我把它们擦掉了。当我使用它们时,我在分配跟踪器中看到了数百个 ArrayListIterator,但由于我删除了它们,我再也看不到它们了。垃圾收集仍然存在:(
  • 你试过在模拟器上运行看看是否得到相同的结果吗?
  • 不,模拟器不支持OpenGLES20。

标签: java android eclipse debugging


【解决方案1】:

好的,我发现了泄漏。事实证明,我在浮点数组上不必要地每帧运行了大约 50 次克隆,但真正让我失望的是,这并没有出现在分配跟踪器中。

更多研究向我展示了这个thread,它似乎声称存在一个 android 错误,其中 array.clone() 操作没有出现在分配跟踪器中。

很沮丧,我花了这么长时间才找到它,但至少现在我每秒只能收集 ​​

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-08
    • 2018-11-25
    • 2018-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 2016-06-02
    相关资源
    最近更新 更多