内存不足错误 - 可能是由于内存泄漏?
Out of Memory error - possibly due to memory leak?
所以我在使用 android 模拟器时遇到了代码问题。我得到同样的错误:Throwing OutOfMemoryError "Failed to allocate a 4776816 byte allocation with 2473998 free bytes and 2MB until OOM"
我有一种感觉,这是由于内存泄漏造成的,因为我为彼此 class 中的每个 class 创建对象,我想这会导致某种循环错误。这在 Java 中是不允许的吗?任何帮助将不胜感激..
代码如下:
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());
}
}
}
玩家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;
}
}
并移动 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();
}
}
}
您 运行 内存不足,因为您的代码将 运行 递归地创建无限数量的对象 BoardActivity
、Move
和 Player
.
怎么样?那么,当 BoardActivity
class 初始化时,行
Move move = new Move();
将创建新的 Move
对象。这反过来将导致行
的执行
Player player = new Player();
从Move
里面class。这将生成一个新的 Player
对象,其中包含行
BoardActivity board = new BoardActivity();
现在这将创建另一个 BoardActivity
对象,这将我们带回到创建无限对象生成循环的开始。
简单的说,BoardActivity
->Move->Player
->BoardActivity
->Move
->Player
.....
我猜 AppCompatActivity
是 android activity。 Android 活动非常繁重,并且在初始化时会分配大量堆内存。这基本上就是您 运行 如此快地耗尽内存的原因。
您不应该以这种方式创建 activity。创建一个并从主 activity 开始,或者使用 AndroidManifest
加载它作为默认 activity
另外,与其为每个按钮创建一个单独的 OnClickListener
,不如创建一个 OnClickListener
并使用 if 语句检查按钮 ID 以确定单击了哪个按钮会更好。
所以我在使用 android 模拟器时遇到了代码问题。我得到同样的错误:Throwing OutOfMemoryError "Failed to allocate a 4776816 byte allocation with 2473998 free bytes and 2MB until OOM" 我有一种感觉,这是由于内存泄漏造成的,因为我为彼此 class 中的每个 class 创建对象,我想这会导致某种循环错误。这在 Java 中是不允许的吗?任何帮助将不胜感激..
代码如下:
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());
}
}
}
玩家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;
}
}
并移动 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();
}
}
}
您 运行 内存不足,因为您的代码将 运行 递归地创建无限数量的对象 BoardActivity
、Move
和 Player
.
怎么样?那么,当 BoardActivity
class 初始化时,行
Move move = new Move();
将创建新的 Move
对象。这反过来将导致行
Player player = new Player();
从Move
里面class。这将生成一个新的 Player
对象,其中包含行
BoardActivity board = new BoardActivity();
现在这将创建另一个 BoardActivity
对象,这将我们带回到创建无限对象生成循环的开始。
简单的说,BoardActivity
->Move->Player
->BoardActivity
->Move
->Player
.....
我猜 AppCompatActivity
是 android activity。 Android 活动非常繁重,并且在初始化时会分配大量堆内存。这基本上就是您 运行 如此快地耗尽内存的原因。
您不应该以这种方式创建 activity。创建一个并从主 activity 开始,或者使用 AndroidManifest
另外,与其为每个按钮创建一个单独的 OnClickListener
,不如创建一个 OnClickListener
并使用 if 语句检查按钮 ID 以确定单击了哪个按钮会更好。