英文:
How to fix java runtime exception in java in android studio?
问题
以下是您提供的代码的翻译部分:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.Random;
import java.util.Stack;
public class GameView extends View {
private Cell[][] cells;
private static final int COLS = 14, ROWS = 5;
private static final float WALL_THICKNESS = 4;
private float cellSize, hMargin, vMargin;
private Paint wallPaint;
private Random random;
public GameView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
wallPaint = new Paint();
wallPaint.setColor(Color.BLACK);
wallPaint.setStrokeWidth(WALL_THICKNESS);
random = new Random();
createMaze();
}
private Cell getNeighbor(Cell cell) {
ArrayList<Cell> neighbors = new ArrayList<>();
// 左边邻居
if (cell.col > 0)
if (!cells[cell.col - 1][cell.row].visited)
neighbors.add(cells[cell.col - 1][cell.row]);
// 右边邻居
if (cell.col < COLS - 1)
if (!cells[cell.col + 1][cell.row].visited)
neighbors.add(cells[cell.col + 1][cell.row]);
// 上面邻居
if (cell.row > 0)
if (!cells[cell.col][cell.row - 1].visited)
neighbors.add(cells[cell.col][cell.row - 1]);
// 下面邻居
if (cell.row < ROWS - 1)
if (!cells[cell.col][cell.row + 1].visited)
neighbors.add(cells[cell.col][cell.row + 1]);
if (neighbors.size() > 0) {
int index = random.nextInt(neighbors.size());
return neighbors.get(index);
}
return null;
}
private void removeWall(Cell current, Cell next) {
if (current.col == next.col && current.row == next.row + 1) {
current.topWall = false;
next.bottomWall = false;
}
if (current.col == next.col && current.row == next.row - 1) {
current.bottomWall = false;
next.topWall = false;
}
if (current.col == next.col + 1 && current.row == next.row) {
current.leftWall = false;
next.rightWall = false;
}
if (current.col == next.col - 1 && current.row == next.row) {
current.rightWall = false;
next.leftWall = false;
}
}
private void createMaze() {
Stack<Cell> stack = new Stack<>();
Cell current, next;
cells = new Cell[COLS][ROWS];
for (int x = 0; x < COLS; x++) {
for (int y = 0; y < ROWS; y++) {
cells[x][y] = new Cell(x, y);
}
}
current = cells[0][0];
current.visited = true;
next = getNeighbor(current);
do {
if (next != null) {
removeWall(current, next);
stack.push(current);
current = next;
current.visited = true;
} else
current = stack.pop();
} while (!stack.empty());
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.GREEN);
int width = getWidth();
int height = getHeight();
if (width / height < COLS / ROWS)
cellSize = width / (COLS + 1);
else
cellSize = height / (ROWS + 1);
hMargin = (width - COLS * cellSize) / 2;
vMargin = (height - ROWS * cellSize) / 2;
canvas.translate(hMargin, vMargin);
for (int x = 0; x < COLS; x++) {
for (int y = 0; y < ROWS; y++) {
if (cells[x][y].topWall)
canvas.drawLine(
x * cellSize,
y * cellSize,
(x + 1) * cellSize,
y * cellSize,
wallPaint);
if (cells[x][y].leftWall)
canvas.drawLine(
x * cellSize,
y * cellSize,
x * cellSize,
(y + 1) * cellSize,
wallPaint);
if (cells[x][y].bottomWall)
canvas.drawLine(
x * cellSize,
(y + 1) * cellSize,
(x + 1) * cellSize,
(y + 1) * cellSize,
wallPaint);
if (cells[x][y].rightWall)
canvas.drawLine(
(x + 1) * cellSize,
y * cellSize,
(x + 1) * cellSize,
(y + 1) * cellSize,
wallPaint);
}
}
}
private class Cell {
boolean
topWall = true,
leftWall = true,
bottomWall = true,
rightWall = true,
visited = false;
int col, row;
public Cell(int col, int row) {
this.col = col;
this.row = row;
}
}
}
英文:
This must be a simple issue that I do not understand how to fix. I am making a program that randomly generates mazes by using cells (the squares) and randomly shuffling their sides. When I try to run the code it crashes and gives me this in logcat:
2020-05-05 01:34:14.798 5891-5891/com.example.maze E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.maze, PID: 5891
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.maze/com.example.maze.MainActivity}: android.view.InflateException: Binary XML file line #19 in com.example.maze:layout/activity_main: Binary XML file line #19 in com.example.maze:layout/activity_main: Error inflating class com.example.maze.GameView
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3333)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3477)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
Caused by: android.view.InflateException: Binary XML file line #19 in com.example.maze:layout/activity_main: Binary XML file line #19 in com.example.maze:layout/activity_main: Error inflating class com.example.maze.GameView
Caused by: android.view.InflateException: Binary XML file line #19 in com.example.maze:layout/activity_main: Error inflating class com.example.maze.GameView
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at android.view.LayoutInflater.createView(LayoutInflater.java:852)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1004)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:161)
at com.example.maze.MainActivity.onCreate(MainActivity.java:12)
at android.app.Activity.performCreate(Activity.java:7990)
at android.app.Activity.performCreate(Activity.java:7979)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3308)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3477)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 167772176 byte allocation with 8388608 free bytes and 110MB until OOM, target footprint 93743400, growth limit 201326592
at java.util.Arrays.copyOf(Arrays.java:3136)
at java.util.Arrays.copyOf(Arrays.java:3106)
2020-05-05 01:34:14.799 5891-5891/com.example.maze E/AndroidRuntime: at java.util.Vector.grow(Vector.java:266)
at java.util.Vector.ensureCapacityHelper(Vector.java:246)
at java.util.Vector.addElement(Vector.java:620)
at java.util.Stack.push(Stack.java:67)
at com.example.maze.GameView.createMaze(GameView.java:108)
at com.example.maze.GameView.<init>(GameView.java:34)
... 28 more
Here is my program below. I think the issue is coming from the stack.push(current) line of code (java 108). This program is not in the main activity class. I left the main activity class untouched when I created the project. This is in its own class called GameView.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.Random;
import java.util.Stack;
public class GameView extends View {
private Cell[][] cells;
private static final int COLS = 14, ROWS = 5;
private static final float WALL_THICKNESS = 4;
private float cellSize, hMargin, vMargin;
private Paint wallPaint;
private Random random;
public GameView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
wallPaint = new Paint();
wallPaint.setColor(Color.BLACK);
wallPaint.setStrokeWidth(WALL_THICKNESS);
random = new Random();
createMaze();
}
private Cell getNeighbor(Cell cell) {
ArrayList<Cell> neighbors = new ArrayList<>();
//left neighbor
if(cell.col > 0)
if(!cells[cell.col-1][cell.row].visited)
neighbors.add(cells[cell.col-1][cell.row]);
//right neighbor
if(cell.col < COLS-1)
if(!cells[cell.col+1][cell.row].visited)
neighbors.add(cells[cell.col+1][cell.row]);
//top neighbor
if(cell.row > 0)
if(!cells[cell.col][cell.row-1].visited)
neighbors.add(cells[cell.col][cell.row-1]);
//bottom neighbor
if(cell.row < ROWS-1)
if(!cells[cell.col][cell.row+1].visited)
neighbors.add(cells[cell.col][cell.row+1]);
if(neighbors.size() > 0) {
int index = random.nextInt(neighbors.size());
return neighbors.get(index);
}
return null;
}
private void removeWall(Cell current, Cell next) {
if(current.col == next.col && current.row == next.row+1) {
current.topWall = false;
next.bottomWall = false;
}
if(current.col == next.col && current.row == next.row-1) {
current.bottomWall = false;
next.topWall = false;
}
if(current.col == next.col+1 && current.row == next.row) {
current.leftWall = false;
next.rightWall = false;
}
if(current.col == next.col-1 && current.row == next.row) {
current.rightWall = false;
next.leftWall = false;
}
}
private void createMaze() {
Stack<Cell> stack = new Stack<>();
Cell current, next;
cells = new Cell[COLS][ROWS];
for(int x = 0; x < COLS; x++) {
for(int y = 0; y < ROWS; y++) {
cells[x][y] = new Cell(x, y);
}
}
current = cells[0][0];
current.visited = true;
next = getNeighbor(current);
do {
if(next != null) {
removeWall(current, next);
stack.push(current);
current = next;
current.visited = true;
} else
current = stack.pop();
} while(!stack.empty());
}
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
canvas.drawColor(Color.GREEN);
int width = getWidth();
int height = getHeight();
if(width/height < COLS/ROWS)
cellSize = width/(COLS+1);
else
cellSize = height/(ROWS+1);
hMargin = (width - COLS * cellSize)/2;
vMargin = (height-ROWS * cellSize)/2;
canvas.translate(hMargin, vMargin);
for(int x = 0; x < COLS; x++) {
for(int y = 0; y < ROWS; y++) {
if(cells[x][y].topWall)
canvas.drawLine(
x * cellSize,
y * cellSize,
(x+1) * cellSize,
y * cellSize,
wallPaint);
if(cells[x][y].leftWall)
canvas.drawLine(
x * cellSize,
y * cellSize,
x * cellSize,
(y+1) * cellSize,
wallPaint);
if(cells[x][y].bottomWall)
canvas.drawLine(
x * cellSize,
(y+1) * cellSize,
(x+1) * cellSize,
(y+1) * cellSize,
wallPaint);
if(cells[x][y].rightWall)
canvas.drawLine(
(x+1) * cellSize,
y * cellSize,
(x+1) * cellSize,
(y+1) * cellSize,
wallPaint);
}
}
}
private class Cell {
boolean
topWall = true,
leftWall = true,
bottomWall = true,
rightWall = true,
visited = false;
int col, row;
public Cell(int col, int row) {
this.col = col;
this.row = row;
}
}
}
答案1
得分: 0
以下是堆栈跟踪的相关部分的翻译:
-
它说应用程序正在尝试分配一个167兆字节的数组(!!),但由于堆已满而失败。
-
它说分配发生在尝试复制数组时。
-
它说这个数组复制发生在扩展
Vector
时。 -
它说
Vector
扩展发生在将元素推入Stack
时。 -
它说
Stack
推入是在您的createMaze
方法中调用的。
简而言之,您的createMaze
方法创建了一个当前深度为数百万个元素的Stack
。
问题出在这个循环中:
do {
if (next != null) {
removeWall(current, next);
stack.push(current);
current = next;
current.visited = true;
} else
current = stack.pop();
} while(!stack.empty());
如果next
不是null
,则“push”,否则“pop”。但在循环中,您在哪里更改next
?
英文:
This is the relevant part of the stacktrace:
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 167772176 byte allocation with 8388608 free bytes and 110MB until OOM, target footprint 93743400, growth limit 201326592
at java.util.Arrays.copyOf(Arrays.java:3136)
at java.util.Arrays.copyOf(Arrays.java:3106)
at java.util.Vector.grow(Vector.java:266)
at java.util.Vector.ensureCapacityHelper(Vector.java:246)
at java.util.Vector.addElement(Vector.java:620)
at java.util.Stack.push(Stack.java:67)
at com.example.maze.GameView.createMaze(GameView.java:108)
at com.example.maze.GameView.<init>(GameView.java:34)
So what does the stacktrace say?
-
It says that the application is attempting to allocate a 167Mbyte array (!!), and that is failing because the heap is full.
-
It says that the allocation happens while it is trying to create a copy of an array
-
It says that this array copy happens while it is expanding a
Vector
-
It says that the
Vector
expansion happens while pushing an element onto aStack
. -
It says that the
Stack
push is being called in yourcreateMaze
method.
In short, your createMaze
method has created a Stack
that is currently many millions of elements deep ... so far.
The problem is in this loop:
do {
if (next != null) {
removeWall(current, next);
stack.push(current);
current = next;
current.visited = true;
} else
current = stack.pop();
} while(!stack.empty());
If next
is not null
, you "push" otherwise you "pop". But where do you change next
in the loop?
专注分享java语言的经验与见解,让所有开发者获益!
评论