加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

难以捉摸的Java内存泄漏

发布时间:2020-12-15 08:47:06 所属栏目:Java 来源:网络整理
导读:我有基于LWJGL的 Java应用程序.我通过排列在3 x 3网格中的9个顶点缓冲区渲染地形.当摄像机移过某个边界时,9个缓冲区要么更新要么用一组新的地形替换.这一切都很好,除了当一个新的地形块添加9元素阵列时,我的内存增加大约5MB.仅此一项就是预期的.不期望的是前
我有基于LWJGL的 Java应用程序.我通过排列在3 x 3网格中的9个顶点缓冲区渲染地形.当摄像机移过某个边界时,9个缓冲区要么更新要么用一组新的地形替换.这一切都很好,除了当一个新的地形块添加9元素阵列时,我的内存增加大约5MB.仅此一项就是预期的.不期望的是前一个地形块占用的5MB内存没有得到清理.

我已经筋疲力尽了我的谷歌,所以我希望有人可以给我一些帮助.我安装并运行了VisualVM.我不明白的是,Windows在大量地形加载和卸载后使用200MB表示我的应用程序.但VisualVM堆转储仅显示12MB.

用于加载地形的游戏循环不在来自“main”的精确线程中运行.谁能指出我正确的方向?我会粘贴一些代码,但是它太大了我不知道要粘贴哪个位.

while(Game.running) {

        time = Sys.getTime();
        dt = (double)((time - lastTime))/1000.0;
        lastTime = time;

        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

        input.pollInput(cam,dt);
        cam.update(terrain.getTerrainHeight());
        sun.render();
        terrain.updateNew(cam.getPosition());
        terrain.render();
        frameRendering();
        //testTriangle();
        Display.update();
    }

有主循环.问题似乎发生在terrain.updateNew()函数中.

这是:

public void updateNew(Vector3f playerPos)
{
    _playerPos.x = playerPos.x;
    _playerPos.y = playerPos.y;
    _playerPos.z = playerPos.z;
    int width = TerrainChunk.CHUNK_WIDTH;
    _westernBounds = _chunks[4].getOrigin().x + 0;
    _easternBounds = _chunks[4].getOrigin().x + width - 0;
    _northernBounds = _chunks[4].getOrigin().z + 0;
    _southernBounds = _chunks[4].getOrigin().z + width - 0;

    if(_playerPos.x < _westernBounds && !_needUpdate)
    {
        _needUpdate = true;
        _inWestBounds = true;
    }

    if(_playerPos.x > _easternBounds && !_needUpdate)
    {
        _needUpdate = true;
        _inEastBounds = true;
    }

    if(_playerPos.z < _northernBounds && !_needUpdate)
    {
        _needUpdate = true;
        _inNorthBounds = true;
    }

    if(_playerPos.z > _southernBounds && !_needUpdate)
    {
        _needUpdate = true;
        _inSouthBounds = true;
    }

    if(_needUpdate)
    {
        long key = 0;
        long key1 = 0;
        long key2 = 0;
        int[] coords = new int[2];
        HashMap<Integer,Long> needed = new HashMap<Integer,Long>();

        coords = calculateChunkCoords(0);
        key1 = coords[0];
        key2 = coords[1];
        key = key1 << 32 | key2;
        needed.put(0,key);

        coords = calculateChunkCoords(1);
        key1 = coords[0];
        key2 = coords[1];
        key = key1 << 32 | key2;
        needed.put(1,key);

        coords = calculateChunkCoords(2);
        key1 = coords[0];
        key2 = coords[1];
        key = key1 << 32 | key2;
        needed.put(2,key);

        coords = calculateChunkCoords(3);
        key1 = coords[0];
        key2 = coords[1];
        key = key1 << 32 | key2;
        needed.put(3,key);

        coords = calculateChunkCoords(4);
        key1 = coords[0];
        key2 = coords[1];
        key = key1 << 32 | key2;
        needed.put(4,key);

        coords = calculateChunkCoords(5);
        key1 = coords[0];
        key2 = coords[1];
        key = key1 << 32 | key2;
        needed.put(5,key);

        coords = calculateChunkCoords(6);
        key1 = coords[0];
        key2 = coords[1];
        key = key1 << 32 | key2;
        needed.put(6,key);

        coords = calculateChunkCoords(7);
        key1 = coords[0];
        key2 = coords[1];
        key = key1 << 32 | key2;
        needed.put(7,key);

        coords = calculateChunkCoords(8);
        key1 = coords[0];
        key2 = coords[1];
        key = key1 << 32 | key2;
        needed.put(8,key);

        // copy the chunks we have into a searchable has map
        HashMap<Long,TerrainChunk> have = new HashMap<Long,TerrainChunk>();
        key1 = _chunks[0]._origin[0];
        key2 = _chunks[0]._origin[1];
        key = key1 << 32 | key2;
        have.put(key,new TerrainChunk(_chunks[0],_chunks[0]._color));
        key1 = _chunks[1]._origin[0];
        key2 = _chunks[1]._origin[1];
        key = key1 << 32 | key2;
        have.put(key,new TerrainChunk(_chunks[1],_chunks[1]._color));
        key1 = _chunks[2]._origin[0];
        key2 = _chunks[2]._origin[1];
        key = key1 << 32 | key2;
        have.put(key,new TerrainChunk(_chunks[2],_chunks[2]._color));
        key1 = _chunks[3]._origin[0];
        key2 = _chunks[3]._origin[1];
        key = key1 << 32 | key2;
        have.put(key,new TerrainChunk(_chunks[3],_chunks[3]._color));
        key1 = _chunks[4]._origin[0];
        key2 = _chunks[4]._origin[1];
        key = key1 << 32 | key2;
        have.put(key,new TerrainChunk(_chunks[4],_chunks[4]._color));
        key1 = _chunks[5]._origin[0];
        key2 = _chunks[5]._origin[1];
        key = key1 << 32 | key2;
        have.put(key,new TerrainChunk(_chunks[5],_chunks[5]._color));
        key1 = _chunks[6]._origin[0];
        key2 = _chunks[6]._origin[1];
        key = key1 << 32 | key2;
        have.put(key,new TerrainChunk(_chunks[6],_chunks[6]._color));
        key1 = _chunks[7]._origin[0];
        key2 = _chunks[7]._origin[1];
        key = key1 << 32 | key2;
        have.put(key,new TerrainChunk(_chunks[7],_chunks[7]._color));
        key1 = _chunks[8]._origin[0];
        key2 = _chunks[8]._origin[1];
        key = key1 << 32 | key2;
        have.put(key,new TerrainChunk(_chunks[8],_chunks[8]._color));


        Set<Entry<Integer,Long>> set = needed.entrySet();
        Iterator<Entry<Integer,Long>> i = set.iterator();
        // Garbage cleanup?
        while(i.hasNext())
        {
            Map.Entry<Integer,Long> me = i.next();
            if(have.containsKey(me.getValue()))
            {
                _chunks[me.getKey()] = null;
                _chunks[me.getKey()] = new TerrainChunk(have.get(me.getValue()),getColor(me.getKey()));
            } else {
                _chunks[me.getKey()].destroy();
                _chunks[me.getKey()] = null;
                _chunks[me.getKey()] = new TerrainChunk(calculateChunkCoords(me.getKey()),getColor(me.getKey()),this);
            }
        }
        _needUpdate = false;
        have.clear();
        needed.clear();
        have = null;
        needed = null;
    }
}

这是创建顶点缓冲区的函数:

private boolean createVertexBuffer()
{
    _vboVertexAttribues = ARBVertexBufferObject.glGenBuffersARB();
    _vboVertexIndices = ARBVertexBufferObject.glGenBuffersARB();
    //_vboVertexTexture = ARBVertexBufferObject.glGenBuffersARB();

    ARBVertexBufferObject.glBindBufferARB(
            ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,_vboVertexAttribues
    );

    ARBVertexBufferObject.glBufferDataARB(
            ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,(VERTEX_SIZE * VERTEX_COUNT),ARBVertexBufferObject.GL_STATIC_DRAW_ARB
    );

    ByteBuffer vertextPositionAttributes = ARBVertexBufferObject.glMapBufferARB(
            ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,ARBVertexBufferObject.GL_WRITE_ONLY_ARB,null
    );

    for(int i = 0; i < VERTEX_COUNT; i++)
    {
        vertextPositionAttributes.putDouble(_vPos[i].x);
        vertextPositionAttributes.putDouble(_vPos[i].y);
        vertextPositionAttributes.putDouble(_vPos[i].z);
        vertextPositionAttributes.putDouble(_vNorm[i].x);
        vertextPositionAttributes.putDouble(_vNorm[i].y);
        vertextPositionAttributes.putDouble(_vNorm[i].z);
        vertextPositionAttributes.putFloat(_color.x);
        vertextPositionAttributes.putFloat(_color.y);
        vertextPositionAttributes.putFloat(_color.z);
        vertextPositionAttributes.putFloat(1.0f);
    }


    vertextPositionAttributes.flip();

    ARBVertexBufferObject.glUnmapBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB);
    ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,0);    

    vertextPositionAttributes.clear();
    vertextPositionAttributes = null;
    // TEXTURE COORDS
    /*ARBVertexBufferObject.glBindBufferARB(
            ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,_vboVertexTexture
            );

    ARBVertexBufferObject.glBufferDataARB(
            ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,(TEXTURE_SIZE * VERTEX_COUNT),ARBVertexBufferObject.GL_STATIC_DRAW_ARB
        );

    ByteBuffer vertexTextureCoords = ARBVertexBufferObject.glMapBufferARB(
            ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,null
        );

    for(int i = 0; i < VERTEX_COUNT; i++)
    {
        vertexTextureCoords.putFloat(_vTex[i].x);
        vertexTextureCoords.putFloat(_vTex[i].y);
    }
    vertexTextureCoords.flip();

    ARBVertexBufferObject.glUnmapBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB);
    ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,0);*/


    ARBVertexBufferObject.glBindBufferARB(
            ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,_vboVertexIndices
    );

    ARBVertexBufferObject.glBufferDataARB(
            ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,(INDEX_SIZE * INDEX_COUNT),ARBVertexBufferObject.GL_STATIC_DRAW_ARB
    );

    ByteBuffer vertexIndices = ARBVertexBufferObject.glMapBufferARB(
            ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,null
    );

    for(int i = 0; i < _nIndices.length; i++)
    {
        vertexIndices.putInt(_nIndices[i]);
    }

    vertexIndices.flip();

    ARBVertexBufferObject.glUnmapBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB);
    ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,0);

    // Cleanup our crap
    _fXs = null;
    _fYs = null;
    _fZs = null;
    _vPos = null;
    _vNorm = null;
    _color = null;
    _nIndices = null;
    _vTex = null;
    vertexIndices.clear();
    vertexIndices = null;
    return true;
}

这是渲染功能:
????public void render()
????{

GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
    GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
    GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
    ARBVertexBufferObject.glBindBufferARB(
            ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,_vboVertexAttribues
    );

    ARBVertexBufferObject.glBindBufferARB(
            ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,_vboVertexIndices
    );

    GL11.glVertexPointer(
            3,GL11.GL_DOUBLE,VERTEX_SIZE,0
    );

    GL11.glNormalPointer(
            GL11.GL_DOUBLE,NORMAL_SIZE
    );

    GL11.glColorPointer(
            4,GL11.GL_FLOAT,POSITION_SIZE + NORMAL_SIZE
    );


    GL11.glDrawElements(
            GL11.GL_TRIANGLE_STRIP,INDEX_COUNT,GL11.GL_UNSIGNED_INT,0
    );

    ARBVertexBufferObject.glBindBufferARB(
            ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB,0
    );

    ARBVertexBufferObject.glBindBufferARB(
            ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,0
    );

    GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
    GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
    GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
}

在此先感谢您的任何帮助或建议.

解决方法

我认为它可能是Java VM从操作系统中分配内存的方式的一个工件,特别是即使堆缩小也不会释放页面,但要保持堆不得不再次增长.

但就代码中的内存泄漏而言,重要的是VisualVM所说的堆大小.如果那是稳定的,那里就没有泄漏.

您还应该考虑Java VM本身使用大量本机库和其他消耗物理或虚拟内存的东西,这为每个Java进程提供了大致恒定的开销.

(This可能也有帮助.)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读