LWJGL을 기반으로하는 Java 응용 프로그램이 있습니다. 3x3 격자로 배열 된 9 개의 꼭지점 버퍼를 통해 지형을 렌더링 중입니다. 카메라가 특정 경계를지나 움직이면 9 개의 버퍼가 업데이트되거나 새로운 지형 집합으로 바뀝니다. 이 모든 것은 잘 작동합니다. 새로운 요소 블록이 9 요소 배열에 추가되면 약 5MB의 메모리가 증가합니다. 이것만으로도 충분합니다. 예상하지 못한 것은 이전 지형 덩어리가 차지하고 있던 5MB의 메모리가 정리되지 않는다는 것입니다.Java 메모리 누수가 감지되지 않음
나는 누군가 내 도움을 줄 수 있기를 바랄 정도로 내 Google-FU를 소진했습니다. 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() 함수에서 발생하는 것 같습니다. 여기
: 렌더링 기능 여기
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;
}
된다 : 여기
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;
}
}
는 정점 버퍼를 생성하는 기능입니다 공공 무효)은 ( {
렌더링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);
}
도움이나 도움을 미리 감사드립니다. .
응용 프로그램에 실제로 메모리가 부족합니까? JVM은 메모리를 자주 공개하지 않으며 GC는 실제로 필요할 때만 실행됩니다. JVM에 실제로 GC를 수행하여 어떤 일이 발생하는지 확인해 보았습니다. JVM이 실제로 메모리를 비울 수 없는지 확인하기 위해 더 낮은 -Xmx 값을 사용해 보셨습니까? – Rich
왜 5MB가 증가 할 것으로 예상됩니까? 각 버퍼는 약 5MB/9 ?? – UmNyobe
가비지 콜렉터를 수동으로 실행했는데, 이는 virtualVM에서 힙 크기를 변경하지만 OS 메모리 할당은 변경하지 않습니다. – jasonlg3d