【发布时间】: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