Fuite de mémoire Java lors de la vérification de l'espace vide dans le tableau


Oh cher Ramasseur d'ordures. J'ai couru sur une erreur java outOfMemory.

Stacktrace:

[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)

Informations recueillies à l'aide de l'analyseur de mémoire Eclipse:

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

La fonction qui est la source de cette erreur outOfMemory est la suivante:

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

BlocksList est un tableau partiellement rempli de la taille de 4096. La fonction est censée vérifier que la première place de la liste est vide (null) afin qu'elle puisse transmettre cet id à la super fonction qui donne l'id au classe de base qui utilise cet id pour créer l'objet et l'ajoute à la liste de blocs.

La fonction getNextEmptyId () est appelée ici:

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;
    }

}

Qui appelle à nouveau cette fonction via 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();
    }
}


Dans AABBPool ligne 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    }

Dans la ligne de bloc 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    }

Si vous avez besoin de plus d'informations, dites-le. Merci pour toute aide.

Author: Pascal Neubert, 2014-01-22

1 answers

Il semble à première vue que votre problème n'est pas la fonction qui recherche l'écart dans votre liste de blocs, mais que chaque bloc que vous construisez est référencé dans cette liste et dans votre GameRegistry.

Peut-être qu'une de ces références persiste d'une manière ou d'une autre lorsque vous essayez de libérer un bloc, cela empêche GC d'effacer sa mémoire et cela provoque votre fuite... c'est juste une idée, s'il vous plaît vérifier.

Veuillez consulter Pourquoi cet exemple de code produit-il une fuite de mémoire? pour explications supplémentaires sur les fuites de mémoire

 0
Author: Jorge_B, 2017-05-23 12:11:42