Reputation:
So I'm having an issue with my code when using the android emulator. I get the same error: Throwing OutOfMemoryError "Failed to allocate a 4776816 byte allocation with 2473998 free bytes and 2MB until OOM" I have a feeling this is due to memory leak as I create objects for each class within each other class and I imagine it's causing some kind of loop error. Is this disallowed in Java? Any help would be much appreciated..
Here is the code:
public class BoardActivity extends AppCompatActivity {
Move move = new Move();
Button buttons[] = new Button[16];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_board);
move.newGame();
buttons[0] = (Button)findViewById(R.id.button1);buttons[0].setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
move.makeMove(move.cups.get(0));
updateButtons();
}});
buttons[1] = (Button)findViewById(R.id.button2);buttons[1].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(1));
updateButtons();
}
});
buttons[2] = (Button)findViewById(R.id.button3);buttons[2].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(2));
updateButtons();
}
});
buttons[3] = (Button)findViewById(R.id.button4);buttons[3].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(3));
updateButtons();
}
});
buttons[4] = (Button)findViewById(R.id.button5);buttons[4].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(4));
updateButtons();
}
});
buttons[5] = (Button)findViewById(R.id.button6);buttons[5].setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
move.makeMove(move.cups.get(5));
updateButtons();
}
});
buttons[6] = (Button)findViewById(R.id.button7);buttons[6].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(6));
updateButtons();
}
});
buttons[7] = (Button)findViewById(R.id.button8);buttons[7].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
updateButtons();
}
});
buttons[8] = (Button)findViewById(R.id.button9);buttons[8].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(8));
updateButtons();
}
});
buttons[9] = (Button)findViewById(R.id.button10);buttons[9].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(9));
updateButtons();
}
});
buttons[10] = (Button)findViewById(R.id.button11);buttons[10].setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
move.makeMove(move.cups.get(10));
updateButtons();
}
});
buttons[11] = (Button)findViewById(R.id.button12);buttons[11].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(11));
updateButtons();
}
});
buttons[12] = (Button)findViewById(R.id.button13);buttons[12].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(12));
updateButtons();
}
});
buttons[13] = (Button)findViewById(R.id.button14);buttons[13].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(13));
updateButtons();
}
});
buttons[14] = (Button)findViewById(R.id.button15);buttons[14].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
move.makeMove(move.cups.get(14));
updateButtons();
}
});
// Still have bug with this button - needs to be sorted
buttons[15] = (Button)findViewById(R.id.button16);buttons[15].setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
updateButtons();
}
});
updateButtons();
}
public void updateButtons(){
for(int i=0; i<buttons.length; i++){
buttons[i].setText(move.cups.get(i).toString());
}
}
}
Player class:
public class Player extends Move{
Random rand = new Random();
BoardActivity board = new BoardActivity();
/**public void setScoreCups(){
if(returnCurrentPlayer()==1){
oppositionScoreCup = cups.get(16);
scoreCup = cups.get(8);
}else{
oppositionScoreCup = cups.get(8);
scoreCup = cups.get(16);
}
}**/
public void setNextPlayer(){
if(returnCurrentPlayer()==1) {
setTurnPlayer(2);
}else if(returnCurrentPlayer()==2){
setTurnPlayer(1);
}
}
public int returnCurrentPlayer(){
if(board.buttons[5].isEnabled()){
return 1;
}else{
return 2;
}
}
public void setRandomPlayer(){
boolean b = rand.nextBoolean();
if(b){
setTurnPlayer(1);
}else{
setTurnPlayer(2);
}
}
public void setTurnPlayer(int n){
if(n==1) {
for (int i = 1; i < 8; i++) {
board.buttons[i].setEnabled(true);
}
for (int i = 9; i < 16; i++) {
board.buttons[i].setEnabled(false);
}
}else if(n==2){
for(int i=1; i<8; i++){
board.buttons[i].setEnabled(false);
}
for(int i=9; i<16; i++){
board.buttons[i].setEnabled(true);
}
}
}
public void setPlayer() {
if ((move.currentCup.pebbleCount == 0) && (move.currentCup != move.scoreCup)) {
Log.d("makeMove.java", "print cup index" + move.cups.indexOf(move.currentCup));
//emptyCupSwitch(currentCup);
move.currentCup.increasePebbleCount();
}
if (move.currentCup == move.scoreCup) {
move.currentCup.increasePebbleCount();
setTurnPlayer(move.currentPlayer);
} else if (move.currentCup != move.scoreCup) {
move.currentCup.increasePebbleCount();
setNextPlayer();
}
}
//needs to be changed
public static int score=0;
public void setScore(int n){
score = n;
}
}
And Move class:
public class Move extends Game{
Player player = new Player();
public Cup oppositionScoreCup; public Cup scoreCup;
int i; int currentPlayer; int cupValue;
int currentIndex; int lastCupIndex = currentIndex + cupValue - 1;
Cup currentCup;
public List<Cup> cups;
public void newGame() {
cups = new ArrayList<>();
//Reset all cups
for (int i = 0; i < 16; i++) {
Cup cup = new Cup(7);
cups.add(i, cup);
}
}
//Returns the cup following the one entered in the parameters
public Cup getNextCup(Cup cup) {
if (cups.indexOf(cup) == 15) {
return cups.get(0);
} else {
return cups.get(cups.indexOf(cup) + 1);
}
}
//Emptys current cup and switches pebbles to opposite side
public void emptyCupSwitch(Cup cup) {
Cup oppCup;
int index = cups.indexOf(cup);
switch(index) {
case 1:
oppCup = cups.get(15);
cups.get(1).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
break;
case 2:
oppCup = cups.get(14);
cups.get(2).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
break;
case 3:
oppCup = cups.get(13);
cups.get(3).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
break;
case 4:
oppCup = cups.get(12);
cups.get(4).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 5:
oppCup = cups.get(11);
cups.get(5).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 6:
oppCup = cups.get(10);
cups.get(6).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 7:
oppCup = cups.get(9);
cups.get(7).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 9:
oppCup = cups.get(7);
cups.get(9).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 10:
oppCup = cups.get(6);
cups.get(10).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 11:
oppCup = cups.get(5);
cups.get(11).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 12:
oppCup = cups.get(4);
cups.get(12).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 13:
oppCup = cups.get(3);
cups.get(13).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 14:
oppCup = cups.get(2);
cups.get(7).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
case 15:
oppCup = cups.get(1);
cups.get(7).pebbleCount += oppCup.pebbleCount;
oppCup.emptyCup();
}
}
//Method for Clicking Cup - Basic move - Skips oppositonScoreCup
public void makeMove(Cup cup) {
cupValue = cup.returnPebbleCount();
currentIndex = cups.indexOf(cup);
currentCup = getNextCup(cup);
cup.emptyCup();
for (i = currentIndex; i < currentIndex + cupValue; i++) {
if (i == lastCupIndex) {
player.setPlayer();
} else if (currentCup == oppositionScoreCup) {
currentCup = getNextCup(currentCup);
} else if (currentCup != oppositionScoreCup) {
currentCup.increasePebbleCount();
currentCup = getNextCup(currentCup);
}
}
if(checkGameOver()){
gameOver();
}
}
}
Upvotes: 1
Views: 287
Reputation: 502
You are running out of memory because your code will run recursively and create an infinite number of objects of BoardActivity
, Move
and Player
.
How? Well, when the BoardActivity
class is initialized, the line
Move move = new Move();
will create new Move
object. This, in turn will result in the execution of the line
Player player = new Player();
from inside the Move
class. This will spawn a new Player
object which contains the line
BoardActivity board = new BoardActivity();
Now this will create another BoardActivity
object and this takes us back to the beginning creating an endless cycle of object spawning.
Simply put, BoardActivity
->Move->Player
->BoardActivity
->Move
->Player
....
I'm guessing the AppCompatActivity
is an android activity. Android activities are pretty heavy and allocates some good amount of heap memory when initialized. This is basically why you are running out of memory so quickly.
You shouldn't be creating an activity this way. Either create one and start from the main activity or load it as the default activity using the AndroidManifest
Also instead of creating a separate OnClickListener
for each button, it would be better to create a single OnClickListener
and check button ids using if statements to determine which button was clicked.
Upvotes: 1