[英]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重现该错误,所以让我解释一下应用程序在做什么:
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并侦听传入的连接。 ServerWorker
-Thread is started which handles incoming packages send through ObjectOutputStreams
and received through ObjectInputStreams
(on both sides). ServerWorker
-Thread,该线程处理通过ObjectOutputStreams
发送并通过ObjectInputStreams
(在两侧)接收的传入包。 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
字段中。 ObjectOutputStream
before sending a changed NetIOResponseUpdate
(because field values differ from the previously sent), os.reset()
is performed. NetIOResponseUpdate
之前重置ObjectOutputStream
(因为字段值与先前发送的值不同), os.reset()
执行os.reset()
。 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.
请让我知道我是否应该提供其他信息或代码。
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.