我正在使用JavaFX来创建一个简单的Messenger客户端。有问题的课程是:
MainMenuController.class:此类处理JavaFX ui逻辑,例如将聊天消息打印到文本区域
Server.class:控制服务器套接字和输入/输出逻辑
Client.class:控制客户端套接字和输入/输出逻辑
我能够在本地主机上完美地运行应用程序,但是当我尝试过快地发送消息时,我的程序会抛出nullpointerexception。我将通过相关代码,然后我将解释我试图解决的问题。
MainMenuController.java(跟踪此函数的异常)
public static void printMessage(String sender, String msg) {
//msgHistory is a textArea
msgHistory.appendText(sender + ": " +msg + "\n");
}
Server.java
try {
servSocket = new ServerSocket(serverPort);
MainMenuController.printMessage("Server running on port: "
+ serverPort + ". . .");
// block till we accept connection request
clientSocket = servSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
// receive and set friend's alias
friendName = in.readLine();
aliasSet = true;
String input;
// while connection is present, poll server socket input for new
// messages
while (true) {
Thread.sleep(100);
input = in.readLine();
if (input == null) {
break;
}
//update status
MainMenuController.printMessage(friendName, input); //Line traced to exception
}
}
Client.java
try {
socket = new Socket (serverAddr, portNum);
MainMenuController.printMessage("Connected!");
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//send server our alias
out.println(myName);
} catch (IOException e) {
System.err.println("Accept failed.");
}
我认为异常是由客户端和服务器同时尝试写入MainMenuController中的textArea引起的。我在服务器打印到textArea之前尝试添加了thread.sleep(x)。我还在MainMenuController类中实现了一个公共锁。在服务器和客户端的每次调用printMessage中,我等到锁定空闲后再调用printMessage方法(我在调用printMessage之前设置了锁,然后在方法返回后释放它)。我把这个代码拿出来让它更具可读性。这些解决方案都没有奏效,我不确定在哪里寻找。
堆栈跟踪:
Exception in thread "Thread-4" java.lang.NullPointerException
at com.sun.javafx.sg.prism.NGTextHelper$TextAttributes.computeLinePadding(NGTextHelper.java:405)
at com.sun.javafx.sg.prism.NGTextHelper$TextAttributes.access$200(NGTextHelper.java:292)
at com.sun.javafx.sg.prism.NGTextHelper.buildTextLines(NGTextHelper.java:2357)
at com.sun.javafx.sg.prism.NGTextHelper.validateText(NGTextHelper.java:1847)
at com.sun.javafx.sg.prism.NGTextHelper.getCaretShape(NGTextHelper.java:1435)
at javafx.scene.text.Text.getDecorationShapes(Text.java:1150)
at javafx.scene.text.Text.impl_geomChanged(Text.java:757)
at javafx.scene.text.Text$1.invalidated(Text.java:214)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:127)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:161)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:67)
at javafx.scene.text.Text.setText(Text.java:188)
at com.sun.javafx.scene.control.skin.TextAreaSkin$17.invalidated(TextAreaSkin.java:610)
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:359)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1034)
at javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1038)
at javafx.scene.control.TextInputControl$TextProperty.invalidate(TextInputControl.java:978)
at javafx.scene.control.TextInputControl$TextProperty.access$200(TextInputControl.java:950)
at javafx.scene.control.TextInputControl$1.invalidated(TextInputControl.java:119)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:155)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.scene.control.TextArea$TextAreaContent.insert(TextArea.java:196)
at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:373)
at javafx.scene.control.TextInputControl.insertText(TextInputControl.java:308)
at javafx.scene.control.TextInputControl.appendText(TextInputControl.java:298)
at application.MainMenuController.printMessage(MainMenuController.java:96)
at application.Server.run(Server.java:79)
at java.lang.Thread.run(Unknown Source)
编辑:此错误仅发生在textArea.appendText(字符串)中。 textArea.setText(string)没有抛出任何异常。
答案 0 :(得分:2)
您不应该从任意线程调用JavaFX方法,而只能从JavaFX Application Thread调用JavaFX方法。在Platform.runLater()来电中包裹您的msgHistory.appendText
。
答案 1 :(得分:0)
您没有检查friendName
是否为null。任何readLine()
调用都可以返回null。
NB在致电readLine()
之前睡觉实际上是浪费时间。它会阻塞,直到数据可用。