java stackoverflowerror 在无限循环中抛出

标签 java memory-leaks out-of-memory infinite-loop stack-overflow

我有以下函数来启动 jsvc 守护进程来接收 UDP 消息:

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

    DatagramPacket dgp = new DatagramPacket(buf, buf.length);
    DatagramSocket sk;

    sk = new DatagramSocket(1000);
    sk.setSoTimeout(0);

    byte[] rcvMsg = null;


    run(sk, dgp, rcvMsg);


}

超时为 0 时,套接字会阻塞,直到收到另一条消息。这会触发以下 while 循环的连续运行:

 MessageConstructor tmc =null;
Message message = null;

public void run(DatagramSocket sk, DatagramPacket dgp, byte[] rcvMsg){
    while(true){
        try {
            sk.receive(dgp);
        } catch (IOException e) {
            e.printStackTrace();
        }
        rcvMsg = dgp.getData();

         tmc = new MessageConstructor();
         message = tmc.constructMessageFromBinary(rcvMsg);

        tmc =null;
        message = null;
     }


}

唯一创建的新对象是下面的 MessageConstructor:

在constructTagMessageFromBinary函数内部,有一个从ByteArrayInputStream填充的消息,它将接收到的UDP消息转换为int。

 public Message constructTagMessageFromBinary(byte[] rcvMsg) {

Message message = new Message();
ByteArrayInputStream bais = new ByteArrayInputStream(rcvMsg);
DataInput input = new DataInputStream(bais);

    try {

        int MsgType = 0;
        MsgType = input.readShort();

        message.setType(MsgType);

        return message;

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return null;
}

最后,该消息是一个 pojo。

公开课消息{

private int type;
 //getters and setters omitted

}

我已将内存泄漏范围缩小到以下几行:

 tmc = new MessageConstructor();
 message = tmc.constructMessageFromBinary(rcvMsg);

如果我将它们注释掉,只要守护进程运行,内存就永远不会增长并保持一致。

我在 MessageConstructor 类中做错了什么才能收到以下 stackoverflowerror:

Service exit with a return value of 143
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.apache.commons.daemon.support.DaemonLoader.start(DaemonLoader.java:243)
Caused by: java.lang.NullPointerException
        at MainDaemon.start(MainDaemon.java:116)
        ... 5 more
Cannot start daemon
Service exit with a return value of 5
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.apache.commons.daemon.support.DaemonLoader.start(DaemonLoader.java:243)
Caused by: java.lang.NullPointerException
        at MainDaemon.start(MainDaemon.java:117)
        ... 5 more
Cannot start daemon
Service exit with a return value of 5
Service exit with a return value of 143
Service exit with a return value of 143
Service exit with a return value of 143
Service exit with a return value of 143
Service exit with a return value of 143
Service exit with a return value of 143
Service exit with a return value of 143
Service exit with a return value of 143
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.apache.commons.daemon.support.DaemonLoader.start(DaemonLoader.java:243)
Caused by: java.lang.StackOverflowError

最佳答案

    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();
            }
        }

此代码似乎没有执行任何 I/O。 incomingBinaryMessage 不是方法调用,它是对现有 byte[] 的对象引用。

循环重复运行,一遍又一遍地创建相同的消息。

通常 GC 应该跟上您的步伐,因为您在每个循环上都会丢弃消息和 MessageCreator 实例。然而,您没有显示的一段代码,Message 的构造函数可以保存对消息的引用(即将它们添加到映射中?)并防止它们被 GC 处理。

关于java stackoverflowerror 在无限循环中抛出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17252365/

相关文章:

java - 组合组件的问题

java - 检查参数化通用抽象类对其实现的强制转换

java - Spring 卡夫卡听正则表达式

java - 何时以及如何将 java 类加载器标记为垃圾收集?

c# - 将巨大的 40000 页 pdf 拆分为单页,itextsharp,outofmemoryexception

java - 在 spring-mvc 中使用服务器发送的事件时出现异常

c++ - 这里有内存泄漏吗?试图通过函数传递对象

c# - 具有 DependencyProperty 的最简单 WPF UserControl 中的内存泄漏

c# - 在这个相对简单的程序中得到 'out of memory' 异常

Java内存泄漏示例