-1

I am struggling to solve this StackOverFlow exception when I try to run my TicTacToe program.

From reading the stack trace I know that the StackOverFlow error is the result of a cyclic relationship. This is because when I instantiate the miniFrame class inside the TicTacToeFrame constructor, A TicTacToeFrame object is used as the parameter for the miniFrame constructor. As a result, this causes infinite recursion.

Exception in thread "main" Exception in thread "main" Exception in thread "main" java.lang.StackOverflowError
    at java.awt.Window.init(Unknown Source)
    at java.awt.Window.<init>(Unknown Source)
    at java.awt.Window.<init>(Unknown Source)
    at java.awt.Dialog.<init>(Unknown Source)
    at java.awt.Dialog.<init>(Unknown Source)
    at javax.swing.JDialog.<init>(Unknown Source)
    at javax.swing.JDialog.<init>(Unknown Source)
    at javax.swing.JDialog.<init>(Unknown Source)
    at miniFrame.<init>(miniFrame.java:12)
    at TicTacToeFrame.<init>(TicTacToeFrame.java:26)
    at miniFrame.<init>(miniFrame.java:9)
    at TicTacToeFrame.<init>(TicTacToeFrame.java:26)
    at miniFrame.<init>(miniFrame.java:9)
    at TicTacToeFrame.<init>(TicTacToeFrame.java:26)
    at miniFrame.<init>(miniFrame.java:9)
    at TicTacToeFrame.<init>(TicTacToeFrame.java:26)
    at miniFrame.<init>(miniFrame.java:9)
    at TicTacToeFrame.<init>(TicTacToeFrame.java:26)
    at miniFrame.<init>(miniFrame.java:9)
    at TicTacToeFrame.<init>(TicTacToeFrame.java:26)

TicTacToeFrameconstructor instantiates the miniFrame dialogBox = new miniFrame (this).

//IMPORT JAVA LIBARARY
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;

public class TicTacToeFrame extends JFrame {
   public char whoseTurn = 'X';   

   public Cell [] [] cells = new Cell [3] [3];
   JLabel jlblStatus = new JLabel ("X's turn to play");

   public boolean gameOver = false;

   public JPanel panel;

   JTextField textField;

public TicTacToeFrame () {
    miniFrame dialogBox = new miniFrame (this);//This is line 26 referred to in the stack trace
    dialogBox.returnName ();
    panel = new JPanel (new GridLayout (3, 3, 0, 0));
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            panel.add (cells [i] [j] = new Cell(this));
        }
    }

    panel.setBorder (new LineBorder (Color.red, 1));
    jlblStatus.setBorder (new LineBorder (Color.yellow, 1));

    add (panel, BorderLayout.CENTER);
    add (jlblStatus, BorderLayout.SOUTH);
}

This is the miniFrame constructor which takes an object of TicTacToeFrame as it's an argument. But I don't understand why the JVM finds a StackOverFlow error on line 9:

import javax.swing.*;
import java.awt.event.*;

public class miniFrame extends JDialog implements ActionListener {
JTextField textField;
JButton Submit;
JLabel playerX;
TicTacToeFrame Label = new TicTacToeFrame ();//This is line 9 referred to in the stack trace. Why does the JVM find an error on this line?

public miniFrame (TicTacToeFrame parent) {
 super (parent);//This is line 12 referred in the stack trace
 textField = new JTextField ("ENTER YOUR NAME", 20);
 Submit = new JButton ("Submit");
 playerX = new JLabel ();

 Submit.addActionListener (this);

 add (playerX);
 add (textField);
 add (Submit);
}

An alternative solution I could use is the -Xss flag to increase the size of the stack frame using the command line. But I feel as though that might be a cop-out.

kinghabz 14
  • 7
  • 1
  • 2
  • 7
    You have a cyclic dependency between the 2 classes. In the parent frame you are doing `miniFrame dialogBox = new miniFrame (this);` and in the child `TicTacToeFrame Label = new TicTacToeFrame ();` Exactly where the lines are indicating the issue. – alexandrum Sep 09 '19 at 20:39
  • 1
    If I may, I would suggest to read about the [Java naming convention](https://www.oracle.com/technetwork/java/codeconventions-135099.html) for better looking code. – alexandrum Sep 09 '19 at 20:42
  • Every TicTacToeFrame creates a miniFrame and every minFrame creates a TicTacToeFrame. Increasing the stack size will just mean it takes longer before it crashes... – John3136 Sep 09 '19 at 20:42
  • Use a debugger. – Raedwald Sep 09 '19 at 21:29

1 Answers1

1

Increasing the size of the stack would only delay the error.

TicTacToeFrame Label = new TicTacToeFrame ();//This is line 9 referred to in the stack trace. Why does the JVM find an error on this line?

Even though this line is not in the constructor, it is executed when a new instance of MiniFrame is constructed. It calls the constructor of TicTacToeFrame, which initializes a new Instance of MiniFrame, leading to this line being executed again. It is part of the infinite loop that is causing the stack overflow, that's why you are getting a stack overflow error on that line.

What is the point of initializing Label directly there, where it is declared? Have you tried initializing it in the constructor of MiniFrame instead? That way, you wouldn't have to initialize it with a new instance, you could initialize it with the parent instance given to the constructor. That would remove the recursion which is causing the stack overflow.

dfu
  • 51
  • 4
  • The reason I initialized Label as an instance variable is as a solution to a null pointer exception I was experiencing. The null pointer exception was preventing me from returning a JLabel to another class. – kinghabz 14 Sep 10 '19 at 17:56
  • How would I initialize the Label reference variable inside the miniFrame constructor using the parent instance? – kinghabz 14 Sep 10 '19 at 17:57
  • I don't actually know java, but assuming it's anything like C#, try adding the line ```Label = parent;``` in the Constructor. If that is the first line of the Constructor, nothing should be able to read that variable before it is initialized, so it would prevent null reference exceptions aswell. – dfu Sep 10 '19 at 18:42