我有以下函数来启动 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/