Search code examples
javastack-overflow

How to fix StackOverflowError when using a high stopping condition 10000


I am trying to solve the following problem:

Given a Player class - an instance of which can communicate with other Players.

The requirements are as follows:

  1. create 2 Player instances
  2. one of the players should send a message to second player (let's call this player "initiator")
  3. when a player receives a message, it should reply with a message that contains the received message concatenated with the value of a counter holding the number of messages this player already sent.
  4. both players should run in the same java process (strong requirement)

Here is my code:

package play;

public class PlayerInteractions {
    static String concatenatedCounts="";

    public static void main(String[] args) {
        //initiator object 
        Player initiator=new Player(1,  "Player1"); 
        //receiver object  
        Player receiver =new Player(2, "Player2"); 
        //initiator sends a message to receiver, as an example we sent the string "message_test"
        initiator.sendMessage("hello", receiver);
        
    }

}
package play;
    
import java.util.ArrayList;
import java.util.List;
    
    
public class Player {
    //player attributes 
    private int id; 
    private String playerName;

    private List<String> sentMessagesList=new  ArrayList<String>(); 
    private String concatenatedPlayerCounts="";

    //getters and setters 
    public List<String> getSentMessagesList() {
        return sentMessagesList;
    }
    public void setSentMessagesList(List<String> sentMessagesList) {
        this.sentMessagesList = sentMessagesList;
    }
    

    public int getID() {
        return id;
    }
    public void setID(int iD) {
        id = iD;
    }

    public String getPlayerName() {
        return playerName;
    }
    public void setPlayerName(String playerName) {
        this.playerName = playerName;
    }
    //ToString
    @Override
    public String toString() {
        return "Player [ID=" + id + ", playerName=" + playerName + "]";
    }
    //Constructor 
    public Player(int iD,  String playerName) {
        super();
        id = iD;
        this.playerName = playerName;
    } 
    //Function to send a message 
    protected void sendMessage(String message, Player receiver) {
        
        //add message to the list of received messages and the list of sent messages 
        this.getSentMessagesList().add(message);
        
        String originalMessage=this.getSentMessagesList().get(0);
        //print messages and count while count is less than 10 sendMessage is called recursively 
        if(receiver.getSentMessagesList().size()<10000) {
            int sentMessagesSize = this.getSentMessagesList().size()-1;
            //concatenate number of messages already sent
            PlayerInteractions.concatenatedCounts=PlayerInteractions.concatenatedCounts+""+this.concatenatedPlayerCounts+""+sentMessagesSize+"";
            //print statement 
            System.out.println(this.getPlayerName()+ ": "+ originalMessage+""+PlayerInteractions.concatenatedCounts+"");
            //recursive call to sendMessage
            receiver.sendMessage(message, this);
        }
    }
    
    
}

The problem that I have is that in the following line when I use 10000 iterations, I receive a StackOverflow error in the following line of code: if(receiver.getSentMessagesList().size()<10000) { The code works fine when I use a low number such as 10 or 100 however it crashes when I use 10000. How can I fix this and not receive this error anymore?


Solution

  • When you send a message here, you will invoke the sendMessage method of the receiver. Which will invoke the method of the sender. Then the receiver again. And so on until you hit the 10000 threshold while just processing the one message.

    A few pointers:

    1. Your assignment says you should return the message along with the number of sent messages. Use an int for this.
    2. You need a separate method for receiving a message.
    3. The assignment does not require you to actually store the messages.

    A minimal solution could the be like this:

    public class Player {
        private int numberOfSentMessages = 0;
    
        public void sendMessage(final String message, final Player receiver) {
            receiver.receiveMessage(message);
            numberOfSentMessages++;
        }
    
        public String receiveMessage(final String message) {
            return message + numberOfSentMessages;
        }
    }