Java 安卓:更新线程会导致GC运行大量内存

Java 安卓:更新线程会导致GC运行大量内存,java,android,multithreading,garbage-collection,Java,Android,Multithreading,Garbage Collection,我正在用Android编写一个有点复杂的游戏引擎 目前我有一个线程用于更新子系统 更新方法内部是基于当前游戏状态更新游戏逻辑的方法 游戏状态有一个场景,该场景已更新。场景由一个根节点组成,从而形成一个简单的场景图结构 根是节点,其子节点也会更新,以此类推 无论如何,这一切都很好,很好用,直到我的日志中有一百万个这样的日志:03-29 09:23:22.866:D/dalvikvm(18554):GC_并发释放511K,52%释放2773K/5767K,外部77K/587K,暂停2ms+3ms 我

我正在用Android编写一个有点复杂的游戏引擎

目前我有一个线程用于更新子系统

更新方法内部是基于当前游戏状态更新游戏逻辑的方法

游戏状态有一个场景,该场景已更新。场景由一个根节点组成,从而形成一个简单的场景图结构

根是节点,其子节点也会更新,以此类推

无论如何,这一切都很好,很好用,直到我的日志中有一百万个这样的日志:03-29 09:23:22.866:D/dalvikvm(18554):GC_并发释放511K,52%释放2773K/5767K,外部77K/587K,暂停2ms+3ms

我已经将泄漏的原因隔离为更新循环,因为当我注释出更新子系统的方法时,没有GC消息。此外,我已经深入到更新循环中进行了注释,直到根节点的子节点更新是GC疯狂运行的时候

(GameLgoic)
public void onUpdate(float deltaTime) 
    {
        if (gameState != null)
            gameState.onUpdate(deltaTime);
    }
(GameState)
public void onUpdate(float deltaTime) 
    {
        scene.onUpdate(deltaTime);
    }
(Scene) 
public void onUpdate(float deltaTime)
    {
        root.onUpdate(deltaTime);
    }
(SceneNode)
public void onUpdate(float deltaTime)
    {
        for (int i = 0; i < children.size(); ++i)
        {
            children.get(i).onUpdate(deltaTime); // Memory leak runs crazily here
        }
    }
(GameLgoic)
更新时的公共无效(浮动deltaTime)
{
如果(游戏状态!=null)
配子状态更新(deltaTime);
}
(游戏状态)
更新时的公共无效(浮动deltaTime)
{
场景更新(deltaTime);
}
(现场)
更新时的公共无效(浮动deltaTime)
{
更新根(deltaTime);
}
(场景节点)
更新时的公共无效(浮动deltaTime)
{
for(int i=0;i

如果我把children.get(I.onUpdate(deltaTime)注释掉,就没有漏洞了!我的脑子里乱七八糟的。谢谢大家。

我在为Android制作游戏时遇到了类似的问题。摆脱这种局面的唯一方法是编写嵌入式C风格的代码。 因此,如果需要循环,请尽可能重用计数变量和边界变量,如下所示:

int i;
int max
void loop(){
    max = bla.size();
    for(i=0; i<max; i++){ ... }
}
inti;
整数最大值
void循环(){
max=bla.size();

对于(i=0;i首先澄清术语-你没有。当你的应用程序的内存使用量不断增长时,会发生内存泄漏,因为它没有释放不再使用的内存。你有相反的问题-你释放了大量未使用的内存,而这些内存必须被释放

释放未使用的内存通常是一件好事;只有当清理释放的内存所需的垃圾收集导致性能问题时,它才会成为一个问题,这就是您在这里看到的

到目前为止,您发布的代码没有什么大问题。问题似乎出在
onUpdate()
方法中,因此您可以为此发布代码

通常,您可以通过尽可能重用对象而不是销毁和创建对象来减少垃圾收集

最后一点,您可以替换:

for (int i = 0; i < children.size(); ++i)
{
    children.get(i).onUpdate(deltaTime); // Memory leak runs crazily here
}

好消息:泄漏的不是onUpdate()调用。而是该方法中的代码。请添加相关的代码段。请显示
子项的定义和关联的
onUpdate
方法。哦,每次调用
size()时
在一个循环中,一只小猫死了。你应该查看官方文档中的性能指南:)子对象的onUpdate方法(arrayList)对于根对象是相同的,只是更新了他们所有的子对象(当前树不太大),但在未来,sceneNodes将处理更新网格动画等。我可能会将其折射到updateChildren方法。但我会在类后检查您的建议。这是一个很好的改进,但正如他提到的
,如果我注释掉children.get(I).onUpdate(deltaTime)没有泄漏!
原因似乎在该方法的代码中,而不是循环本身……在本例中,
for(Child c:children)
语法可能也很方便。我只是扩展了我的答案来涵盖这一点:迭代器也是GC收集的对象,所以不幸的是,这不是选项。这似乎是我应该做的。我会在Classis之后检查它。我会稍后试一试!谢谢伙计。
for (SomeClass child : children) {
    child.onUpdate(deltaTime);
}