Java程序一开始运行正常,但随后导致内存泄漏
我正在做一个项目,尝试使用神经网络来学习如何玩跳棋游戏。在训练我的网络时,我必须运行许多游戏的模拟(10000多个游戏)。当使用Intellij的内存查看器检查堆内存时,一切似乎正常。每个CheckerGame对象及其相关字段(CheckerPieces、GameBoard等)似乎最终都会被java的垃圾收集器回收。这意味着一旦跳棋游戏完成,游戏的资源就会被正确地处理 然而,在运行了一段时间的训练程序之后,Java的垃圾收集器似乎决定停止回收我的游戏对象,然后随着游戏对象的堆积,我最终得到一个OutOfMemory错误。 这是我所说的一个例子 显然有一些内存泄漏,但这对我来说毫无意义,因为该程序大部分时间都正确地回收了游戏资源 编辑:代码Java程序一开始运行正常,但随后导致内存泄漏,java,memory-leaks,heap,heap-memory,Java,Memory Leaks,Heap,Heap Memory,我正在做一个项目,尝试使用神经网络来学习如何玩跳棋游戏。在训练我的网络时,我必须运行许多游戏的模拟(10000多个游戏)。当使用Intellij的内存查看器检查堆内存时,一切似乎正常。每个CheckerGame对象及其相关字段(CheckerPieces、GameBoard等)似乎最终都会被java的垃圾收集器回收。这意味着一旦跳棋游戏完成,游戏的资源就会被正确地处理 然而,在运行了一段时间的训练程序之后,Java的垃圾收集器似乎决定停止回收我的游戏对象,然后随着游戏对象的堆积,我最终得到一个O
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();
}
}
}
训练代码(记分员不断被调用,游戏结果返回到神经网络):
公共类NeuralPlayerRandom{
专用NEATNetwork网络;
私有静态整数播放操作=1;
公共NeutnalPlayerLandom(NEATNetwork网络){
这个网络=网络;
}
公共整数记分员(){
int n=0;
System.out.println(“玩家迭代:+playerOperation”);
对于(int i=0;i<100;i++){
系统输出打印(“I:+I+”);
n+=this.doIteration();
}
播放操作++;
返回n/2;
}
}
私有内部迭代(){
CheckersGame=新CheckersGame();
game.initializeGame();
game.getBluePlayer().setNetwork(this.network);
while(game.getWinner()=-2){
游戏。转身();
}
int winStatus=game.getWinner();
game=null;
返回温斯塔斯;
}
}
}
public class LegalMove{
私人游戏板;
私有游戏板;
私人游戏板;跳转文件;
私人法律动议;
私人法律动议;
私人移动方向;
公共LegalMove(GameBoardTile旧文件、GameBoardTile新文件、LegalMove之前移动、LegalMove之后移动、GameBoardTile跳转文件、移动方向){
this.oldTile=oldTile;
this.newTile=newTile;
this.moveBefore=moveBefore;
this.moveAfter=moveAfter;
this.jumpedTile=jumpedTile;
这个方向=方向;
}
公共LegalMove(GameBoardTile oldTile、GameBoardTile NewFile、LegalMove moveBefore、LegalMove moveAfter、MoveDirections){
this.oldTile=oldTile;
this.newTile=newTile;
this.moveBefore=moveBefore;
this.moveAfter=moveAfter;
这个方向=方向;
}
公共阵列列表GetTotalJumpedFiles(){
ArrayList totalJumpedTiles=新的ArrayList();
LegalMove moveToCheck=此;
while(moveToCheck!=null){
添加(moveToCheck.getJumpedTile());
moveToCheck=moveToCheck.getMoveBefore();
}
返回总跳跃文件;
}
公共游戏板Tile GetJumpedFile(){
返回跳转文件;
}
public int returnNewY(){
return newfile.returnY();
}
public int returnNewX(){
return newfile.returnX();
}
公共GameBoardTile GetNewFile(){
返回新文件;
}
公共GameBoardTile getOldTile(){
归还旧瓷砖;
}
公共无效setMoveAfter(LegalMove moveAfter){
this.moveAfter=moveAfter;
}
公共阵列列表getPastMoves(){
ArrayList pastMoves=新建ArrayList();
LegalMove moveToCheck=moveBefore;
while(moveToCheck!=null){
添加(moveToCheck);
moveToCheck=moveToCheck.getMoveBefore();
}
集合。反向(过去移动);
添加(这个);
回击动作;
}
公共法律移动getMoveBefore(){
之前返回;
}
公共法律移动getMoveAfter(){
返回后移动;
}
公共字符串toString(){
如果(oldTile!=null)
返回“\nOld:+oldTile+”\n新:+newTile+“\n”;
其他的
返回“\nOld:开始“+”\n新:“+newfile+”\n”;
}
//返回此移动树中需要执行的第一个操作
public LegalMove getRootMove(){
LegalMove moveToCheck=此;
while(moveToCheck.getMoveBefore()!=null){
moveToCheck=moveToCheck.getMoveBefore();
}
返回moveToCheck;
}
//捕捉到这一合法行动之前的所有“跳跃”片段
//返回捕获的片段的ArrayList
公共阵列列表captureJumpedPieces(){
ArrayList jumpedPieces=新建ArrayList();
LegalMove moveToCheck=此;
while(moveToCheck!=null){
if(moveToCheck.getJumpedFile()!=null){
添加(moveToCheck.getJumpedFile().getCurrentPiece());
移动到check.getJumpedFile().getCurrentPiece().capturePiece();
moveToCheck=moveToCheck.getMoveBefore();
}否则{
//System.out.println(“移动”+此+“没有跳转片段”);
moveToCheck=moveToCheck.getMoveBefore();
}
}
返回跳线;
}
公共校验页getoldpoice(){
返回oldTile.getCurrentPiece();
}
公共移动方向getDirection(){
返回方向;
}
公共布尔等于(LegalMove移动){
返回(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.getMoveBefore();
temp.moveAfter=null;
临时跳线文件=空;
temp.oldTile=null;
temp.newfile=null;
temp.moveAfter=null;
温度=零;
}
}
}
我遗漏了许多代码部分和不相关的片段我认为这是您的问题:
public ArrayList<GameBoardTile> getTotalJumpedTiles() {
ArrayList<GameBoardTile> totalJumpedTiles = new ArrayList<>();
LegalMove moveToCheck = this;
while (moveToCheck != null) {
totalJumpedTiles.add(moveToCheck.getJumpedTile());
moveToCheck = moveToCheck.getMoveBefore();
}
return totalJumpedTiles;
}
公共阵列列表getTotalJumpe
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;
}
}
public ArrayList<GameBoardTile> getTotalJumpedTiles() {
ArrayList<GameBoardTile> totalJumpedTiles = new ArrayList<>();
LegalMove moveToCheck = this;
while (moveToCheck != null) {
totalJumpedTiles.add(moveToCheck.getJumpedTile());
moveToCheck = moveToCheck.getMoveBefore();
}
return totalJumpedTiles;
}