快速通信消息时,Java客户端/服务器线程空指针异常 [英] Java client / server thread null pointer exception when quickly communicating messages

查看:324
本文介绍了快速通信消息时,Java客户端/服务器线程空指针异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用JavaFX来创建一个简单的Messenger客户端。有问题的类是:

I'm using JavaFX to create a simple messenger client. The classes in question are:

MainMenuController.class:此类处理JavaFX ui逻辑,例如将聊天消息打印到文本区域

MainMenuController.class: this class handles JavaFX ui logic such as printing chat messages to text area

Server.class:控制服务器套接字和输入/输出逻辑

Server.class: controls server socket and in/out logic

Client.class:控制客户端套接字和输入/输出逻辑

Client.class: controls client socket and in/out logic

我能够在本地主机上完美地运行应用程序,但是当我尝试过快地发送消息时,我的程序会抛出nullpointerexception。我将通过相关代码,然后我会解释我试图解决这个问题的方法。

I'm able to run the application perfectly on local host, except my program throws a nullpointerexception when I try to send messages too quickly. I'll past the relevant code, and then I'll explain what I've tried to solve this bug.

MainMenuController.java(追溯到此函数的异常)

MainMenuController.java (exception traced to this function)

public static void printMessage(String sender, String msg) {
    //msgHistory is a textArea
    msgHistory.appendText(sender + ": " +msg + "\n");
}

Server.java

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

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之前设置了锁,然后在方法返回后释放它)。我把这个代码拿出来让它更具可读性。这些解决方案都没有起作用,我不确定在哪里看。

I believe the exception is caused by the client and server trying to write to the textArea in MainMenuController at the same time. I've experimented with adding a thread.sleep(x) before the server prints to textArea. I've also implemented a public lock in the MainMenuController class. In each call to printMessage in both the server and client, I wait until the lock is free before calling the printMessage method (I set the lock before calling printMessage, then free it once the method has returned). I took this code out to make it more readable. Neither of these solutions have worked and I'm not sure where to look.

堆栈跟踪:

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(字符串)不会引发异常。

This error only occurs with textArea.appendText(string). No exception is thrown with textArea.setText(string).

推荐答案

您不应该从任意线程调用JavaFX方法,但只能从JavaFX应用程序线程。在 msgHistory.appendText %28java.lang.Runnable%29rel =nofollow> Platform.runLater()调用。

You are not supposed to call JavaFX methods from an arbitrary thread, but only from the JavaFX Application Thread. Wrap your msgHistory.appendText in a Platform.runLater() call.

这篇关于快速通信消息时,Java客户端/服务器线程空指针异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆