2017-02-14 30 views
-3

Я работаю над проектом, который пытается использовать нейронную сеть, чтобы научиться играть в шашки. Обучая мою сеть, я должен запускать симуляции многих игр (10000+ игр). При проверке памяти кучи с помощью программы просмотра памяти Intellij все выглядит нормально. Каждый объект CheckerGame и связанные с ним поля (CheckerPieces, GameBoard и т. Д.), Похоже, в конечном итоге перерабатываются сборщиком мусора java. Это означает, что как только игра с шашками закончится, ресурсы игры будут правильно утилизированы.Java-программа начинается нормально, но затем приводит к утечке памяти

После запуска программы обучения немного дольше, похоже, что сборщик мусора Java решает прекратить переработку моих игровых объектов, а затем я в конечном итоге получаю OutOfMemoryError, когда игровые объекты накапливаются. Вот пример того, что я говорю о memory leak.

Существует, очевидно, некоторая утечка памяти, но для меня это не имеет смысла, поскольку программа правильно перерабатывает игровые ресурсы большую часть времени.

EDIT: Код

public class CheckersGame { 
private GameBoard board; 
private Player redPlayer; 
private Player bluePlayer; 

private boolean isBlueTurn; 

private int winner = -2; 
private int redGamesWon = 0; 
private int blueGamesWon = 0; 

private int turnNumber = 0; 
private int blueTurnNumber = 0; 

public boolean gameover = false; 

public CheckersGame() { 

} 

public void initializeGame() { 
    winner = -2; 
    redGamesWon = 0; 
    blueGamesWon = 0; 
    turnNumber = 0; 
    blueTurnNumber = 0; 

    redPlayer = new RedPlayer(); 
    bluePlayer = new BluePlayer(); 
    board = new GameBoard(redPlayer, bluePlayer); 
    redPlayer.setBoard(board); 
    bluePlayer.setBoard(board); 

    isBlueTurn = false; 
    board.setUpGameBoard(); 
} 

public void turn() { 
    Random rng = new Random(); 
    try { 
     LegalMove[] possibleMovesRed = redPlayer.getAllPossibleValidMoves(); 
     LegalMove[] possibleMovesBlue = bluePlayer.getAllPossibleValidMoves(); 

     if (turnNumber == 150) { 
      winner = 0; 
      System.out.println("Tie " + NeuralNet.testint + "/" + NeuralNet.otherint + " | " + blueTurnNumber); 
      NeuralNet.testint = 0; 
      NeuralNet.otherint = 0; 
     } 
     if (board.whoWon(possibleMovesBlue, possibleMovesRed) == redPlayer) { 
      winner = -1; 
      System.out.println("Red Won " + NeuralNet.testint + "/" + NeuralNet.otherint + " | " + blueTurnNumber); 
      NeuralNet.testint = 0; 
      NeuralNet.otherint = 0; 
      redGamesWon++; 
     } else if (board.whoWon(possibleMovesBlue, possibleMovesRed) == bluePlayer) { 
      winner = 1; 
      System.out.println("Blue Won " + NeuralNet.testint + "/" + NeuralNet.otherint + " | " + blueTurnNumber); 
      NeuralNet.testint = 0; 
      NeuralNet.otherint = 0; 
      blueGamesWon++; 
     } else { 
      if (isBlueTurn) { //Blue turn (NN) 
       LegalMove nextMove = NeuralNet.getMoveNN(bluePlayer.getNetwork(), bluePlayer.convertBoard(), possibleMovesBlue, bluePlayer); 
       bluePlayer.movePiece(nextMove); 
       isBlueTurn = false; 
       blueTurnNumber++; 
      } else { // Red's turn (random) 

       int upperBound = possibleMovesRed.length; 
       LegalMove randomMove = possibleMovesRed[(rng.nextInt(upperBound))]; 
       redPlayer.movePiece(randomMove); // executes random move 
       isBlueTurn = true; 
      } 


      // gc 
      for (LegalMove move : possibleMovesBlue) { 
       move.clearTree(); 
      } 

      for (LegalMove move : possibleMovesRed) { 
       move.clearTree(); 
      } 

      possibleMovesBlue = null; 
      possibleMovesRed = null; 
      turnNumber++; 
     } 
    } catch (InvalidMoveException ime) { 
     ime.printCustomError(); 
    } 
} 

}

Training Code (scorePlayer получает постоянно называют и результаты игры возвращается к нейронной сети):

public class NeuralPlayerRandom { 
private NEATNetwork network; 
private static int playerIteration = 1; 

public NeuralPlayerRandom(NEATNetwork network) { 
    this.network = network; 
} 


public int scorePlayer() { 
     int n = 0; 
     System.out.println("Player Iteration: " + playerIteration); 

     for (int i = 0; i < 100; i++) { 
      System.out.print("I: " + i + " "); 
      n += this.doIteration(); 
     } 
     playerIteration++; 
     return n/2; 
    } 
} 

private int doIteration() { 
     CheckersGame game = new CheckersGame(); 
     game.initializeGame(); 
     game.getBluePlayer().setNetwork(this.network); 

     while (game.getWinner() == -2) { 
      game.turn(); 
     } 
     int winStatus = game.getWinner(); 
     game = null; 

     return winStatus; 
    } 
} 

}

public class LegalMove { 
private GameBoardTile oldTile; 
private GameBoardTile newTile; 
private GameBoardTile jumpedTile; 

private LegalMove moveBefore; 
private LegalMove moveAfter; 

private MoveDirections direction; 

public LegalMove(GameBoardTile oldTile, GameBoardTile newTile, LegalMove moveBefore, LegalMove moveAfter, GameBoardTile jumpedTile, MoveDirections direction) { 
    this.oldTile = oldTile; 
    this.newTile = newTile; 
    this.moveBefore = moveBefore; 
    this.moveAfter = moveAfter; 
    this.jumpedTile = jumpedTile; 
    this.direction = direction; 
} 

public LegalMove(GameBoardTile oldTile, GameBoardTile newTile, LegalMove moveBefore, LegalMove moveAfter, MoveDirections direction) { 
    this.oldTile = oldTile; 
    this.newTile = newTile; 
    this.moveBefore = moveBefore; 
    this.moveAfter = moveAfter; 
    this.direction = direction; 
} 

public ArrayList<GameBoardTile> getTotalJumpedTiles() { 
    ArrayList<GameBoardTile> totalJumpedTiles = new ArrayList<>(); 

    LegalMove moveToCheck = this; 
    while (moveToCheck != null) { 
     totalJumpedTiles.add(moveToCheck.getJumpedTile()); 
     moveToCheck = moveToCheck.getMoveBefore(); 
    } 

    return totalJumpedTiles; 
} 

public GameBoardTile getJumpedTile() { 
    return jumpedTile; 
} 

public int returnNewY() { 
    return newTile.returnY(); 
} 

public int returnNewX() { 
    return newTile.returnX(); 
} 

public GameBoardTile getNewTile() { 
    return newTile; 
} 

public GameBoardTile getOldTile() { 
    return oldTile; 
} 

public void setMoveAfter(LegalMove moveAfter) { 
    this.moveAfter = moveAfter; 
} 

public ArrayList<LegalMove> getPastMoves() { 
    ArrayList<LegalMove> pastMoves = new ArrayList<>(); 
    LegalMove moveToCheck = moveBefore; 
    while(moveToCheck != null) { 
     pastMoves.add(moveToCheck); 
     moveToCheck = moveToCheck.getMoveBefore(); 
    } 

    Collections.reverse(pastMoves); 
    pastMoves.add(this); 
    return pastMoves; 
} 

public LegalMove getMoveBefore() { 
    return moveBefore; 
} 

public LegalMove getMoveAfter() { 
    return moveAfter; 
} 

public String toString() { 
    if (oldTile != null) 
     return "\nOld: " + oldTile + "\nNew: " + newTile + "\n"; 
    else 
     return "\nOld: BEGINNING" + "\nNew: " + newTile + "\n"; 
} 

// Returns the first that needs to be made in this move tree 
public LegalMove getRootMove() { 
    LegalMove moveToCheck = this; 
    while(moveToCheck.getMoveBefore() != null) { 
     moveToCheck = moveToCheck.getMoveBefore(); 
    } 

    return moveToCheck; 
} 

// Captures all "jumped" pieces up to this legal move 
// Returns ArrayList of pieces captured 
public ArrayList<CheckerPiece> captureJumpedPieces() { 
    ArrayList<CheckerPiece> jumpedPieces = new ArrayList<>(); 
    LegalMove moveToCheck = this; 

    while (moveToCheck != null) { 
     if (moveToCheck.getJumpedTile() != null) { 
      jumpedPieces.add(moveToCheck.getJumpedTile().getCurrentPiece()); 
      moveToCheck.getJumpedTile().getCurrentPiece().capturePiece(); 

      moveToCheck = moveToCheck.getMoveBefore(); 
     } else { 
      //System.out.println("Move " + this + " has no jumped pieces"); 
      moveToCheck = moveToCheck.getMoveBefore(); 
     } 
    } 

    return jumpedPieces; 
} 

public CheckerPiece getOldPiece() { 
    return oldTile.getCurrentPiece(); 
} 

public MoveDirections getDirection() { 
    return direction; 
} 

public boolean equals(LegalMove move) { 
    return (oldTile == move.oldTile && newTile == move.newTile && jumpedTile == move.jumpedTile && direction == move.getDirection()); 
} 

public void clearTree() { 
    LegalMove moveToCheck = moveBefore; 

    while (moveToCheck != null) { 
     LegalMove temp = moveToCheck; 
     moveToCheck = moveToCheck.getMoveBefore(); 

     temp.moveAfter = null; 
     temp.jumpedTile = null; 
     temp.oldTile = null; 
     temp.newTile = null; 
     temp.moveAfter = null; 
     temp = null; 
    } 
} 

}

я ушел из серии участков кода и частей, которые не имеют отношения

+0

Как мы можем найти утечку памяти без какого-либо кода? – shmosel

+0

Это нехорошо, но мы не можем вам помочь, если вы не показываете код –

+0

Также по какой-то причине утечка памяти происходит быстрее на моем ноутбуке linux, чем на моем рабочем столе Windows. – Smaugy

ответ

0

Я думаю, что это ваша проблема:

public ArrayList<GameBoardTile> getTotalJumpedTiles() { 
    ArrayList<GameBoardTile> totalJumpedTiles = new ArrayList<>(); 

    LegalMove moveToCheck = this; 
    while (moveToCheck != null) { 
     totalJumpedTiles.add(moveToCheck.getJumpedTile()); 
     moveToCheck = moveToCheck.getMoveBefore(); 
    } 

    return totalJumpedTiles; 
} 

Я не пошел через остальную часть кода в посмотрите, что произойдет с этим ArrayList, но если вы продолжаете создавать новые и никогда не чистите их, я вижу, где это быстро станет утечкой.

+0

или, может быть, объекты 'LegalMove' также кажутся проблемой,' public ArrayList getPastMoves() ' –