简体   繁体   English

重置ObjectOutputStream时,摆动:EDT NullPointerException

[英]Swing: EDT NullPointerException when resetting ObjectOutputStream

I am really struggling with following nasty Exception thrown within the Swing-Thread: 我真的很努力在Swing-Thread中引发以下令人讨厌的异常:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.plaf.basic.BasicScrollBarUI.layoutHScrollbar(BasicScrollBarUI.java:762)
at javax.swing.plaf.basic.BasicScrollBarUI.layoutContainer(BasicScrollBarUI.java:870)
at java.awt.Container.layout(Container.java:1508)
at java.awt.Container.doLayout(Container.java:1497)
at java.awt.Container.validateTree(Container.java:1693)
at java.awt.Container.validateTree(Container.java:1702)
at java.awt.Container.validate(Container.java:1628)
at javax.swing.RepaintManager$3.run(RepaintManager.java:704)
at javax.swing.RepaintManager$3.run(RepaintManager.java:702)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:701)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1719)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:749)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:702)
at java.awt.EventQueue$3.run(EventQueue.java:696)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:719)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Since I'm not able to reproduce the error for a SSCCE, let me just explain what the application is doing: 由于我无法为SSCCE重现该错误,所以让我解释一下应用程序在做什么:

  • The Main -function calls the Ui -Class extending JFrame , which builds the GUI. Main函数调用Ui -Class扩展JFrame ,以构建GUI。 Also, a ServerSocket -Thread is started and listens for incoming connections. 同样,启动ServerSocket -Thread并侦听传入的连接。
  • If a client connects, a new ServerWorker -Thread is started which handles incoming packages send through ObjectOutputStreams and received through ObjectInputStreams (on both sides). 如果客户端连接,则会启动一个新的ServerWorker -Thread,该线程处理通过ObjectOutputStreams发送并通过ObjectInputStreams (在两侧)接收的传入包。
  • The client requests an NetIORequestUpdate filled with information from the server every second. 客户端NetIORequestUpdate从服务器请求一个NetIORequestUpdate填充了信息。 The server then collects the information and stores them in fields of the new NetIOResponseUpdate . 然后,服务器收集信息并将其存储在新的NetIOResponseUpdate字段中。
  • Since I need to reset the ObjectOutputStream before sending a changed NetIOResponseUpdate (because field values differ from the previously sent), os.reset() is performed. 由于我需要在发送更改的NetIOResponseUpdate之前重置ObjectOutputStream (因为字段值与先前发送的值不同), os.reset()执行os.reset()
  • For the first time, this NetIOResponseUpdate is being send (and os.reset() excecuted), everything works like a charm. 第一次发送此NetIOResponseUpdate (并执行了os.reset() ),所有操作都像一个超级按钮。 But after then, every call to the reset() -function throws above-noted exception. 但此后,每次对reset()函数的调用都会引发上述异常。

The GUI or components are not modified while processing the NetIORequestUpdate and filling the NetIOResponseUpdate with information. GUI或部件,同时处理不被修改NetIORequestUpdate并填充NetIOResponseUpdate用信息。

Still, if I skip resetting the ObjectOutputStream , above exception is not thrown. 不过,如果我跳过重置ObjectOutputStream ,则不会引发上述异常。

I encapsulated every Swing-Component creation and modification with SwingUtilities.invokeLater . 我使用SwingUtilities.invokeLater封装了每个Swing-Component的创建和修改。

Am I missing something? 我想念什么吗? I would welcome any hint or advices regarding this problem. 我欢迎有关此问题的任何提示或建议。 Please let me know if I should provide additional information or code. 请让我知道我是否应该提供其他信息或代码。

Code-Examples 代码示例

NetIOServerWorker NetIOServerWorker

public class NetIOServerWorker implements Runnable {
    @Override
    public final void run() {
        // ... establish / accept connection and initialize Streams like:
        // outStream = new ObjectOutputStream(client.getOutputStream())
        //  inStream = new ObjectInputStream(client.getInputStream())

        while ((request = (NetIORequest) inStream.readObject()) != null) {
            // Processes the request, e.g. build response package
            response = request.process();

            send(response);

            outStream.reset(); // -- This nasty little piece of fluff
        }
    }
}

NetIORequestUpdate NetIORequestUpdate

public class NetIORequestUpdate implements NetIORequest, Serializable {


    private static final long serialVersionUID = -1578148718545111344L;

    @Override
    public final NetIOResponse process() {
        return new NetIOResponseUpdate();
    }

}

NetIOResponseUpdate NetIOResponseUpdate

public class NetIOResponseUpdate implements NetIOResponse, Serializable {

    private static final long serialVersionUID = -7965101237058494053L;

    private NetIOPackage data;

    public NetIOResponseUpdate() {
        data = new NetIOPackage();
        data.setState(DataModel.getState());
    }

    @Override
    public void process() {

    }

}

GUI Creation GUI创建

public final class Ui extends JFrame {
    // Constructor is private since this is a Singleton
    private Ui() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(800, 600));

        // Start GUI-Construction
        invokeInDispatchThreadIfNeeded(new Runnable() {
            @Override
            public void run() {
                build();
                pack();
                setVisible(true);
            }
        });
    }

    private void build() {

        setBounds(100, 100, 754, 529);
        getContentPane().setLayout(new BorderLayout(0, 0));

        UiComponentStatusPanel pnlStatus = new UiComponentStatusPanel(); // extends JPanel
        JScrollPane scrollStatus = new JScrollPane(pnlStatus);
        getContentPane().add(scrollStatus, BorderLayout.CENTER);
    }

    public static void invokeInDispatchThreadIfNeeded(final Runnable runnable) {
        if (EventQueue.isDispatchThread()) {
            runnable.run();
        } else {
            SwingUtilities.invokeLater(runnable);
        }
    }
}

NullPointerException in java implies that an object is used without initialization. Java中的NullPointerException表示使用的对象无需初始化。 Now let's trace it back, reset is not the problem but outstream. 现在让我们追溯一下,重置不是问题,而是下游。 Once outstream is not-null then reset would work. 一旦流出不为空,则重置将起作用。 Check the line that initializes outstream and make sure that the parameter you are passing into that constructor is indeed returning something valid (client.getOutputStream()).It simply implies that the client is not returning a valid outPutStream which is either a problem from the client.. Trace it back in that direction (use a debugger) and let's see what you find 检查初始化流的行,并确保传递给该构造函数的参数确实返回了有效的值(client.getOutputStream()),这仅表示客户端未返回有效的outPutStream,这可能是由于客户端..朝那个方向追溯(使用调试器),让我们看看您发现了什么

Thanks for helping me get on the right track. 感谢您帮助我步入正轨。 A solution has been found. 找到了解决方案。

As it turned out, the error lies in an other branch of the project: 事实证明,错误在于项目的另一个分支:

To 'callback' my GUI after changes in the data model have been made, I used an Interface UiNotifierEvent with a single function void refreshUi(); 在对数据模型进行更改后,要“回调”我的GUI,我使用了一个接口UiNotifierEvent和一个函数void refreshUi(); . Since i then add a reference to the Ui -Instance to a field uiCallback in the DataModel -Class, i also need to run uiCallback.refreshUI(); 由于我随后将对Ui -Instance的引用添加到DataModel -Class的字段uiCallback中,因此我还需要运行uiCallback.refreshUI(); within the EDT. 在EDT中。 Even if the function body is empty. 即使函数体为空。

This is perfectly logical. 这是完全合乎逻辑的。 What is not, is that resetting the OutputStream has an influence on this exception. 不是,重置OutputStream会对此异常产生影响。

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

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