我使用java nio组装了一个简单的echo类型服务器应用程序。虽然它能够写入数据,但它总是抛出以下异常。任何人都可以解释为什么会这样吗?我的代码如下。在创建包含run方法的线程之前,我确保key.isAcceptable()
为真。
线程“pool-1-thread-2”中的异常 显示java.lang.NullPointerException
ExecutorService pool = Executors.newFixedPool(5);
...
try {
pool.execute(
new Thread() {
@Override public void run() {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = null;
try {
sc = ssc.accept();
String response = "Server thread (" + Thread.currentThread().getId() + ") Current time: " + new Date();
ByteBuffer bytes = encoder.encode(CharBuffer.wrap(response));
sc.write(bytes);
} catch (java.io.IOException e) {
System.out.println("Exception: " + e.getMessage());
} finally {
try {
if (sc.isOpen()) sc.close(); // This is the line causing the exception to be thrown. If the check is changed to (sc != null) no exceptions are thrown.
} catch (java.io.IOException e) {
System.out.println("Exception: " + e.getMessage());
}
}
}
}
);
} catch (java.lang.Exception e) {
System.out.println("Interrupted!");
}
线程“pool-1-thread-2”中的异常 60java.lang.NullPointerException
at EchoServer$1.run(EchoServer.java:61) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExec
utor.java:886) at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor) 的.java:908) 在java.lang.Thread.run(Thread.java:619)
答案 0 :(得分:0)
我猜测ssc.accept返回的SocketChannel为null,这反过来暗示ServerSocketChannel处于非阻塞模式,并且没有挂起的连接。
答案 1 :(得分:0)
ServerSocketChannel
的Javadoc说:
If this channel is in non-blocking mode then this method will immediately
return null if there are no pending connections. Otherwise it will block
indefinitely until a new connection is available or an I/O error occurs.
您是否确定ssc.accept()
因为这个原因没有返回null
?
答案 2 :(得分:0)
正如@IainM和@QuantumMechanic所建议的,你没有检查'sc'是否为null。如果NPE出现在sc.close()中,'sc'为null,我会说你有一个NPE调用sc.write(),另一个在finally {}块中调用sc.close()。
您也没有检查write()的结果,因此您可能正在编写部分消息,或者根本没有任何内容。你对sc.isOpen()也有一个完全没有意义的测试。在此代码中它为null或open,没有其他可能性。
我不知道如果没有读取任何输入,你怎么能把这个东西称为echo服务器。
这不是使用NIO的方法。整个想法是你不需要额外的线程。整个设计都存在严重问题。
你也在打印“中断!”在任何异常上,并通过不打印其消息或堆栈跟踪来隐藏实际异常。这也不是使用异常的方法。