2012-01-30 14 views
3

私はLWJGLに基づいたJavaアプリケーションを持っています。私は、3 x 3グリッドに配置された9つの頂点バッファを使って地形を描画しています。カメラが特定の境界を超えて移動すると、9つのバッファが更新されるか、新しい地形のセットに置き換えられます。これはすべてうまくいきます。ただし、新しい要素ブロックが9要素配列に追加された場合、約5MBのメモリが増加します。これだけでも期待されます。予期しないことは、以前の地形チャンクが占めていた5MBのメモリがクリーンアップされていないことです。Javaのメモリリークがありません

私は自分のGoogle-fuを使い果たしてしまったので、誰かが私に助けてくれることを願っています。 VisualVMをインストールして実行しています。私が理解していないことは、地形の読み込みと読み込みを数多く行った後、Windowsが私のアプリケーションを200MBと言うことを示しているということです。しかし、VisualVMのヒープダンプは12MBしかありません。

地形をロードするためのゲームループは、「メイン」からのセパレートスレッドで実行されていません。誰かが私を正しい方向に向けることができますか?私はいくつかのコードを貼り付けるだろうが、その大きさは貼り付けるビットがわからない。

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, 
      (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); 
} 

ご協力いただきありがとうございました。

+1

アプリケーションのメモリが不足していませんか? JVMはメモリを頻繁に解放せず、GCは本当に必要なときにのみ実行されます。実際にGCを実行して何が起こるかをJVMに問い合わせてみましたか? JVMが実際にメモリを解放できないかどうかを確認するために、-Xmxの値を下げてみましたか? – Rich

+0

なぜあなたは5Mbの増加を期待していますか?各バッファは約5MB/9インチですか? – UmNyobe

+0

ガベージコレクタを手動で実行しました。これは、仮想メモリのヒープサイズを変更しますが、OSのメモリ割り当ては変更しません。 – jasonlg3d

答えて

4

JavaVMがOSからメモリを割り当てる方法、特にヒープが縮小してもページを解放しない傾向がありますが、ヒープが再び成長しなければならない場合に備えておくことができます。

しかし、コード内のメモリリークが懸念される限り、重要なのはVisualVMがヒープサイズを指定したことです。安定していればそこには漏れはありません。

また、Java VM自体には、物理​​メモリまたは仮想メモリを消費する多くのネイティブライブラリやその他のものが使用されているため、Javaプロセスごとにほぼ一定のオーバーヘッドが発生します。

Thisも役立つかもしれない。)

+0

面白い読んでいただきありがとうございます。 – jasonlg3d

2

漏れが基本となるネイティブライブラリの内部で起こっていてもよいです。 LWJGLはネイティブのCライブラリ(OpenGL、OpenALなど)にバインドされているようですが、公開されていない表示用の一時的なメモリバッファがあると思われます。 VisualVMがなぜ12 MB(彼が世話しているオブジェクト)を表示するのか、そしてWindowsは200 MB(JVMとGCライブラリの両方で作成されたデータ)を表示するのはなぜでしょうか。

フレームワークを正しく使用していますか?

EDIT:

私は、この特定のライブラリに慣れていないですので、私は誤解されるかもしれないが、実際に あなたが操作 \メモリ割り当てのためのネイティブライブラリを使用しています。

は、すべての罰金をやっているようだが、私はあなたのバッファを割り当てる

ARBBufferObject.glGenBuffersARB

に気づきました。あなたは

ARBBufferObject.glDeleteBuffersARB

を呼び出すか、メモリに保持されます。このバッファを終了するまでように、この方法は、Cネイティブをラップしています。 createVertexBuffer()によって作成されたデータのライフサイクル、呼び出し回数、およびあなたとGPUの両方がこれで終了していないときにバッファを削除する必要があります。

もう一度私はOpenGlのこの側面を知らないので、誰かがあなたを助ける可能性が高いです。 あなたがAPI of ARBBufferObjectC++ Wiki

+0

私はそうだと思います。しかし、私はLWJGLに新しいので、私はそうでない可能性を排除するつもりはない。元の投稿に頂点作成機能を貼り付けました。 – jasonlg3d

1

で説明したものと同じである答えは簡単であることに気づく:あなたは「vertextPositionAttributes」で頂点を置くバッファはおそらく、それが制御GCの外に存在することを意味するものダイレクトバッファであり、ヒープであり、JVisualVMには見えません。

関連する問題