了解Java NIO套接字通道中NullPointerException的原因

时间:2011-05-12 21:01:56

标签: java nio nonblocking

我使用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)

3 个答案:

答案 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的方法。整个想法是你不需要额外的线程。整个设计都存在严重问题。

你也在打印“中断!”在任何异常上,并通过不打印其消息或堆栈跟踪来隐藏实际异常。这也不是使用异常的方法。