难以捉摸的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; } 这是渲染功能: 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可能也有帮助.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |