java stackoverflowerror thrown in infinite loop

前端 未结 3 1729
挽巷
挽巷 2021-01-26 09:31

I have the following function that starts a jsvc daemon for receiving UDP messages:

 @Override
public void start() throws Exception {
    byte[] buf = new byte[1         


        
相关标签:
3条回答
  • 2021-01-26 09:37

    I'm not 100% sure on this, so I'm going to offer more than one suggestion in the hope that some combination of them fixes your problem. I'll also be "typing out loud" so forgive me if you are an advanced user and some of this is really obvious.

    You have an essentially infinite loop. This loop creates a byte array object that has data assigned to it. You create a MessageCreator reference and assign an object to it. You create a null Message reference, enter a try block, and then assign an object (value) to that reference. That assignment, or specifically the method creating the assignment, is the problem, so let's look at that.

    Your createMessage method takes in a byte array which is a copy of the value of the original byte array (rcvMsg). It is its own reference, but points to the same object on the heap. Inside the actual method, you create a Message reference and object. The BAIS reference is created and is pointed to the corresponding BAIS object, which takes in the byte array reference. This means the BAIS object is pointing to the ORIGINAL byte array values. Then you have the DIS, which essentially locally encapsulates the BAIS.

    The try block creates an int reference to a value of 0, which you then immediately reset to be the value of input.readShort(). This reads in the value from the ORIGINAL byte array. You set the message type to be that value, and return the message.

    When you exit the method, the reference to the message object you created is destroyed. Fortunately, you transfer that reference via the return method. So that object is safe. Unfortunately, your input stream is left open! The jvm might leave this alone since it is still open, I'm not sure. If it does, the more important information information is that it still has a reference to the byte array values, thereby keeping them alive. The next time your loop executes, it discards the old rcvMsg reference, but NOT THE OBJECT IT POINTS TO because that object still has a reference. With each iteration, you have more and more byte arrays sitting on the heap, until you run out of memory.

    When you comment out the method call, you never get to open (and leave open) the data stream, and so the underlying object (the byte array) never has a persistant reference, and so is destroyed by the garbage collector.

    TLDR: Close your stream. Add input.close(); before return message; in your createMessage method (may require an updated try/catch).

    Again, not sure about this, but to my warped sense of logic, it makes sense.

    0 讨论(0)
  • 2021-01-26 09:52
        public void run() {             
            while(!stopped){
    
                byte[] rcvMsg = incomingBinaryMessage;
    
                MessageCreator tmc = new MessageCreator();
                Message message = null;
                try {
                    message = tmc.createMessage(rcvMsg);
                System.out.println(message);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
    

    This code does not appear to do any I/O. incomingBinaryMessage is not a method invocation, it is an object reference to an existing byte[].

    The loop runs repeatedly creating the same message over and over.

    Normally GC should keep up with you since you're discarding the messages and MessageCreator instance on every loop. However, the one piece of code you haven't shown, the constructor for Message could be saving a reference to the messages (i.e. adding them to a map?) and preventing them from being GC'ed.

    0 讨论(0)
  • 2021-01-26 09:59

    the problem was that I open a database connection in the loop without closing it.

    0 讨论(0)
提交回复
热议问题