检查数组中的空白空间时Java内存泄漏

时间:2014-01-22 08:26:02

标签: java arrays memory memory-leaks minecraft

哦,亲爱的,垃圾收集器。 我遇到了java outOfMemory错误。

堆栈跟踪:

[09:44:10] 2014-01-22 09:44:10 [INFO] [STDERR] java.lang.OutOfMemoryError: Java heap space
[09:44:11] 2014-01-22 09:44:10 [INFO] [STDERR]  at net.minecraft.util.AABBPool.getAABB(AABBPool.java:50)
[09:44:11] 2014-01-22 09:44:11 [INFO] [STDERR]  at net.minecraft.block.Block.getCollisionBoundingBoxFromPool(Block.java:602)
[09:44:12] 2014-01-22 09:44:12 [INFO] [STDERR]  at net.minecraft.block.Block.addCollisionBoxesToList(Block.java:568)
[09:44:14] 2014-01-22 09:44:14 [INFO] [STDERR]  at net.minecraft.world.World.getCollidingBoundingBoxes(World.java:1684)
[09:44:15] 2014-01-22 09:44:14 [INFO] [STDERR]  at net.minecraft.entity.player.EntityPlayerMP.<init>(EntityPlayerMP.java:187)
[09:44:17] 2014-01-22 09:44:15 [INFO] [STDERR]  at net.minecraft.server.management.ServerConfigurationManager.createPlayerForUser(ServerConfigurationManager.java:389)
[09:44:18] 2014-01-22 09:44:17 [INFO] [STDERR]  at net.minecraft.server.integrated.IntegratedServerListenThread.networkTick(IntegratedServerListenThread.java:91)
[09:44:19] 2014-01-22 09:44:18 [INFO] [STDERR]  at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:691)
[09:44:20] 2014-01-22 09:44:19 [INFO] [STDERR]  at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:587)
[09:44:22] 2014-01-22 09:44:20 [INFO] [STDERR]  at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:129)
[09:44:23] 2014-01-22 09:44:22 [INFO] [STDERR]  at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:484)
[09:44:24] 2014-01-22 09:44:23 [INFO] [STDERR]  at net.minecraft.server.ThreadMinecraftServer.run(ThreadMinecraftServer.java:16)
[09:44:33] 2014-01-22 09:44:24 [SEVERE] [Minecraft-Server] Encountered an unexpected exception OutOfMemoryError
[09:44:33] java.lang.OutOfMemoryError: Java heap space
[09:44:33]  at net.minecraft.util.AABBPool.getAABB(AABBPool.java:50)
[09:44:33]  at net.minecraft.block.Block.getCollisionBoundingBoxFromPool(Block.java:602)
[09:44:33]  at net.minecraft.block.Block.addCollisionBoxesToList(Block.java:568)
[09:44:33]  at net.minecraft.world.World.getCollidingBoundingBoxes(World.java:1684)
[09:44:33]  at net.minecraft.entity.player.EntityPlayerMP.<init>(EntityPlayerMP.java:187)
[09:44:33]  at net.minecraft.server.management.ServerConfigurationManager.createPlayerForUser(ServerConfigurationManager.java:389)
[09:44:33]  at net.minecraft.server.integrated.IntegratedServerListenThread.networkTick(IntegratedServerListenThread.java:91)
[09:44:33]  at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:691)
[09:44:33]  at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:587)
[09:44:33]  at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:129)
[09:44:33]  at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:484)
[09:44:33]  at net.minecraft.server.ThreadMinecraftServer.run(ThreadMinecraftServer.java:16)

使用Eclipse Memory Analyzer收集的信息:

The thread net.minecraft.server.ThreadMinecraftServer @ 0xbdf43f30 Server thread keeps local variables with total size 935,606,320 (87.86%) bytes.

The memory is accumulated in one instance of "java.lang.Object[]" loaded by "<system class loader>".

Keywords
java.lang.Object[]

Shortest Paths To the Accumulation Point
Class Name  Shallow Heap    Retained Heap
|-> java.lang.Object[17176655] @ 0xee3868b8    68,706,640   935,599,248
\-> elementData java.util.ArrayList @ 0xc22cbc80    24  935,599,272
-\-> listAABB net.minecraft.util.AABBPool @ 0xbff74570    40    935,599,312
--\-> value java.lang.ThreadLocal$ThreadLocalMap$Entry @ 0xc1844bc0    32   935,599,344
---\-> [58] java.lang.ThreadLocal$ThreadLocalMap$Entry[64] @ 0xbe0330b0    272  935,605,248
----\-> table java.lang.ThreadLocal$ThreadLocalMap @ 0xbe036680    24   935,605,272
-----\-> threadLocals net.minecraft.server.ThreadMinecraftServer @ 0xbdf43f30 Server thread Thread    120   935,606,320

Accumulated Object by class:
net.minecraft.util.AxisAlignedBB | Number of Objects: 13,545,197 | Used Heap Size: 866,892,608 | Retained Heap Size: 866,892,608

作为outOfMemory错误源的函数是:

private static int getNextEmptyId()
{
    int temp = 0;
    for(; temp < blocksList.length; temp++)
    {
        if(blocksList[temp] == null)
        {
           break;
        }
    }
    return temp;
}

blocksList是一个部分填充的数组,大小为4096。 该函数应该检查列表中的第一个空是空(null),因此它可以将此id传递给超级函数,该函数将id提供给基类​​,该基类使用此id创建对象并将其添加到blocksList。

此处调用函数getNextEmptyId():

public class ModBlock extends Block
{

...

    public ModBlock(String name, Material material)
    {
        super(getNextEmptyId(), material);
        GameRegistry.registerBlock(this, name);
        this.setTextureName("terracraft/" + name);
        this.setUnlocalizedName(name);
        this.stepSound = soundStoneFootstep;
    }

}

然后通过super再次调用此函数:

public Block(int par1, Material par2Material)
{
    this.stepSound = soundPowderFootstep;
    this.blockParticleGravity = 1.0F;
    this.slipperiness = 0.6F;

    if (blocksList[par1] != null)
    {
        throw new IllegalArgumentException("Slot " + par1 + " is already occupied by " + blocksList[par1] + " when adding " + this);
    }
    else
    {
        this.blockMaterial = par2Material;
        blocksList[par1] = this;
        this.blockID = par1;
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        opaqueCubeLookup[par1] = this.isOpaqueCube();
        lightOpacity[par1] = this.isOpaqueCube() ? 255 : 0;
        canBlockGrass[par1] = !par2Material.getCanBlockGrass();
    }
}


在AABBPool第50行:

44    public AxisAlignedBB getAABB(double par1, double par3, double par5, double par7, double par9, double par11)
45    {
46        AxisAlignedBB axisalignedbb;
47
48        if (this.nextPoolIndex >= this.listAABB.size())
49        {
50            axisalignedbb = new AxisAlignedBB(par1, par3, par5, par7, par9, par11);
51           this.listAABB.add(axisalignedbb);
52        }
53        else
54        {
55            axisalignedbb = (AxisAlignedBB)this.listAABB.get(this.nextPoolIndex);
56            axisalignedbb.setBounds(par1, par3, par5, par7, par9, par11);
57        }
58
59        ++this.nextPoolIndex;
60        return axisalignedbb;
61    }

在Block 602中:

600    public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
601    {
602        return AxisAlignedBB.getAABBPool().getAABB((double)par2 + this.minX, (double)par3 + this.minY, (double)par4 + this.minZ, (double)par2 + this.maxX, (double)par3 + this.maxY, (double)par4 + this.maxZ);
603    }

如果您需要更多信息,请说明。 谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

第一眼看到您的问题不是寻找阻止列表中的差距的函数,而是您构建的每个块都在该列表和GameRegistry中被引用。

当你尝试释放一个块时,也许其中一个引用会以某种方式存在,这会阻止GC擦除其内存并导致泄漏...这只是一个想法,请检查它。

请查看Why does this code sample produce a memory leak?以获取有关内存泄漏的进一步说明