简体   繁体   English

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

[英]Understanding Cause of NullPointerException in Java NIO Socket Channel

I've put together a simple echo type server app using java nio. 我使用java nio整理了一个简单的回显类型服务器应用程序。 While it is able to write the data, it always throws the following exception. 尽管它能够写入数据,但始终会引发以下异常。 Can anyone explain why this is happening? 谁能解释为什么会这样? My code is below. 我的代码如下。 Before the thread containing the run method is created I ensure the key.isAcceptable() is true. 在创建包含run方法的线程之前,请确保key.isAcceptable()为true。

Exception in thread "pool-1-thread-2" java.lang.NullPointerException 线程“ 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!");
}               

Exception in thread "pool-1-thread-2" 60java.lang.NullPointerException 线程“ 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) at java.lang.Thread.run(Thread.java:619) utor.java:886),位于java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor .java:908),位于java.lang.Thread.run(Thread.java:619)

我猜想ssc.accept返回的SocketChannel为null,这反过来意味着ServerSocketChannel处于非阻塞模式,并且没有挂起的连接。

The Javadoc for ServerSocketChannel says: 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.

Are you sure ssc.accept() isn't returning null for just that reason? 您确定ssc.accept()并非仅出于该原因返回null吗?

As suggested by @IainM and @QuantumMechanic, you aren't checking 'sc' for null. 正如@IainM和@QuantumMechanic所建议的那样,您无需检查'sc'是否为null。 If the NPE arises in sc.close(), 'sc' was null, I would say you got an NPE calling sc.write(), and another one in the finally{} block calling sc.close(). 如果NPE出现在sc.close()中,则“ sc”为null,我想说您有一个NPE调用sc.write(),而在finally {}块中又有一个NPE调用sc.close()。

You also aren't checking the result of the write(), so you may be writing partial messages or indeed nothing at all. 您也没有检查write()的结果,因此您可能正在编写部分消息,或者根本什么也没写。 You also have a completely pointless test for sc.isOpen(). 您还对sc.isOpen()进行了完全没有意义的测试。 It is either null or open in this code, there is no other possibility. 在此代码中为null或打开,没有其他可能性。

And I don't know how you can call this thing an echo server when it doesn't read any input. 而且我不知道当它不读取任何输入时如何将其称为回显服务器。

This is not the way to use NIO. 这不是使用NIO的方法。 The whole idea is that you don't need extra threads. 整个想法是,您不需要额外的线程。 There is something seriously wrong with your entire design. 您的整个设计存在严重问题。

You are also lying to yourself by printing "Interrupted!" 您还可以通过打印“ Interrupted!”来对自己说谎。 on any exception, and concealing the actual exception by not printing its message or stack trace. 任何异常,并通过不打印其消息或堆栈跟踪来隐藏实际异常。 This is not the way to use exceptions either. 这也不是使用异常的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM