Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
难以捉摸的Java内存泄漏_Java_Memory Leaks_Lwjgl - Fatal编程技术网

难以捉摸的Java内存泄漏

难以捉摸的Java内存泄漏,java,memory-leaks,lwjgl,Java,Memory Leaks,Lwjgl,我有一个基于LWJGL的Java应用程序。我通过9个顶点缓冲区渲染地形,这些缓冲区排列在一个3 x 3的网格中。当相机移动超过某个边界时,9个缓冲区要么更新,要么替换为一组新地形。这一切都很好,除了当一个新的地形块被添加到9元素阵列中时,我得到了大约5MB的内存增加。这是意料之中的事。不可预料的是,前一个terrain区块占用的5MB内存没有得到清理 我已经用尽了我的谷歌浏览器,所以我希望有人能给我一些帮助。我已安装并运行VisualVM。我不明白的是,在大量的地形加载和卸载之后,Windows

我有一个基于LWJGL的Java应用程序。我通过9个顶点缓冲区渲染地形,这些缓冲区排列在一个3 x 3的网格中。当相机移动超过某个边界时,9个缓冲区要么更新,要么替换为一组新地形。这一切都很好,除了当一个新的地形块被添加到9元素阵列中时,我得到了大约5MB的内存增加。这是意料之中的事。不可预料的是,前一个terrain区块占用的5MB内存没有得到清理

我已经用尽了我的谷歌浏览器,所以我希望有人能给我一些帮助。我已安装并运行VisualVM。我不明白的是,在大量的地形加载和卸载之后,Windows显示了我的应用程序,比如说200MB。但是VisualVM堆转储仅显示12MB

加载地形的游戏循环没有在“main”的seprerate线程中运行。谁能给我指出正确的方向吗?我想粘贴一些代码,但它太大了,我不知道该粘贴哪一位

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

提前感谢您提供的任何帮助或建议。

我认为这可能是Java虚拟机从操作系统分配内存方式的产物,尤其是它们倾向于即使堆缩小也不释放页面,而是保留页面以防堆再次增长

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

您还应该考虑到Java VM本身使用了大量本机库和其他消耗物理或虚拟内存的东西,这使得每个Java进程的开销大致保持不变


(可能也有帮助。)

泄漏可能发生在底层本机库中。LWJGL似乎绑定到了本机C库(OpenGL、OpenAL等),我怀疑有一些临时内存缓冲区用于显示,它们从未被释放。这将解释为什么VisualVM只显示12MB(他正在处理的对象),而Windows显示200MB(JVM创建的数据,仍然在GC中,以及C库中使用的数据)

您确定您正确使用了该框架吗

编辑:

我可能弄错了,因为我不熟悉这个特定的库,但是 实际上,您正在使用本机库进行内存分配\操作

看起来你一切都很好,但我注意到了

ARBBufferObject.glGenBuffersARB

分配你的缓冲区。此方法正在包装一个C本机,因此在调用

ARBBufferObject.glDeleteBuffersARB

或者终止此缓冲区将在内存中持久化。您应该确定由
createVertexBuffer()
创建的数据的生命周期、调用它的次数,并在您和GPU都未完成此操作时删除缓冲区

再说一次,我不知道OpenGl的这一面,所以有人可能会帮助你。
您注意到,与中讨论的相同,答案很简单:将顶点放入“vertextPositionAttributes”中的缓冲区很可能是一个直接缓冲区,这意味着它存在于GC控制的堆之外,对JVisualVM不可见。

您的应用程序是否真的内存不足?JVM不经常释放内存,GC只在真正需要时运行。您是否尝试过让JVM实际执行GC以查看发生了什么?您是否尝试过使用一个较低的-Xmx值来查看JVM是否确实无法释放内存?为什么您希望增加5Mb?每个缓冲区大约为5mb/9??我已手动运行垃圾收集器,它确实会更改virtualVM中的堆大小,但不会更改操作系统内存分配。用于计算顶点缓冲区的数据相当大。大量向量3f’代码中有大的顶点缓冲区吗?它最初是在哪里创建的?它是否在
calculateChunkCoords()中
。如果是,也发代码。我想我是。然而,我是LWJGL的新手,所以我不会排除我不是的可能性。我已将顶点创建函数粘贴到原始帖子中。
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, 
            (VERTEX_SIZE * VERTEX_COUNT),
            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,
            ARBVertexBufferObject.GL_WRITE_ONLY_ARB,
            (TEXTURE_SIZE * VERTEX_COUNT),
            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,
            ARBVertexBufferObject.GL_WRITE_ONLY_ARB,
            (INDEX_SIZE * INDEX_COUNT),
            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;
}
    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,
            VERTEX_SIZE,
            NORMAL_SIZE
    );

    GL11.glColorPointer(
            4, 
            GL11.GL_FLOAT, 
            VERTEX_SIZE, 
            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);
}