【问题标题】:Swing: EDT NullPointerException when resetting ObjectOutputStreamSwing:重置 ObjectOutputStream 时的 EDT NullPointerException
【发布时间】:2015-02-04 14:13:57
【问题描述】:

我真的在努力解决 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)

由于我无法重现 SSCCE 的错误,所以让我解释一下应用程序在做什么:

  • Main-函数调用 Ui-Class 扩展 JFrame,从而构建 GUI。此外,还会启动一个ServerSocket-Thread 并侦听传入的连接。
  • 如果客户端连接,则会启动一个新的ServerWorker-Thread 来处理通过ObjectOutputStreams 发送和通过ObjectInputStreams 接收的传入包(在双方)。
  • 客户端每秒向服务器请求一个NetIORequestUpdate,其中填充了信息。然后服务器收集信息并将它们存储在新的NetIOResponseUpdate 的字段中。
  • 由于我需要在发送更改后的NetIOResponseUpdate 之前重置ObjectOutputStream(因为字段值与之前发送的不同),所以执行os.reset()
  • 这是第一次,这个NetIOResponseUpdate 被发送(并且os.reset() 被执行),一切都像一个魅力。但在那之后,对reset()-function 的每次调用都会引发上述异常。

在处理NetIORequestUpdate 并用信息填充NetIOResponseUpdate 时,不会修改GUI 或组件。

不过,如果我跳过重置 ObjectOutputStream,则不会引发上述异常。

我用SwingUtilities.invokeLater封装了每一个Swing-Component的创建和修改。

我错过了什么吗?我欢迎有关此问题的任何提示或建议。如果我应该提供其他信息或代码,请告诉我。

代码示例

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

public class NetIORequestUpdate implements NetIORequest, Serializable {


    private static final long serialVersionUID = -1578148718545111344L;

    @Override
    public final NetIOResponse process() {
        return new 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创建

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);
        }
    }
}

【问题讨论】:

  • 请对代码和代码 sn-ps、HTML/XML 或输入/输出等结构化文档使用代码格式(而不是 <pre> 标记)。为此,请选择文本并单击消息发布/编辑表单顶部的{} 按钮。

标签: java multithreading swing user-interface nullpointerexception


【解决方案1】:

Java 中的 NullPointerException 意味着在没有初始化的情况下使用对象。 现在让我们回溯一下,reset 不是问题,而是outstream。一旦 outstream 不为空,则重置将起作用。 检查初始化 outstream 的行,并确保您传递给该构造函数的参数确实返回了有效的东西 (client.getOutputStream())。它只是意味着客户端没有返回有效的 outPutStream,这可能是来自客户端.. 朝那个方向追溯(使用调试器),让我们看看你发现了什么

【讨论】:

  • 感谢您的回复。实际上,OutputStream 工作得很好,问题不在于服务器和客户端之间的通信,而更多的是在重置 OutputStream 时 Swing 出现问题。我应该提到,由于在 Swing-Thread 中抛出异常(每秒!),它不会中断应用程序或通信。
  • 我不确定这是否会导致 NullPointerException。尝试使用调试器,看看你有什么
【解决方案2】:

感谢您帮助我走上正轨。已找到解决方案。

事实证明,错误在于项目的另一个分支:

为了在数据模型发生更改后“回调”我的 GUI,我使用了一个接口 UiNotifierEvent 和一个函数 void refreshUi();。由于我随后将对Ui-Instance 的引用添加到DataModel-Class 中的字段uiCallback,因此我还需要在EDT 中运行uiCallback.refreshUI();。即使函数体为空。

这完全合乎逻辑。不是,重置OutputStream 对此异常有影响。

【讨论】:

    猜你喜欢
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 2015-01-03
    • 2014-03-31
    • 2015-04-23
    相关资源
    最近更新 更多