FX doesn't always warn you (as it would mean putting thread checks everywhere).

The first trace however shows that the change to the TextArea did not originate from the FX thread.

--John

On 19/12/2023 18:17, Frank Delporte wrote:
Thanks John, quick test with this change indeed seems to solve the problem!
Platform.runLater(() -> searchAction.appendAnswer(token));
I totally missed this and I didn't notice anything in the logs that was pointing in this direction.

Best regards
Frank Delporte

/Want to have coding-fun? /
/Check my blog //https://webtechie.be// <https://webtechie.be/>/and book "Getting started with Java on Raspberry Pi" on //https://webtechie.be/books// <https://webtechie.be/books/>





---- On Tue, 19 Dec 2023 09:14:51 +0100 *Frank Delporte <fr...@webtechie.be>* wrote ---

        Hi, while experimenting with a ChatGPT-like user interface, I
        found a crashing JVM with different types of errors when
        streaming the response towards a TextArea. This is probably
        caused by too fast refreshes of the text as pieces of content
        are received within the same milliseconds:

        19/12/2023 08:51:57.874 | DocsAnswerService                  
        | onNext               | INFO     | Appending ' better'
        19/12/2023 08:51:57.874 | DocsAnswerService                  
        | onNext               | INFO     | Appending ' performance'
        19/12/2023 08:51:57.875 | DocsAnswerService                  
        | onNext               | INFO     | Appending ' after'
        19/12/2023 08:51:57.978 | DocsAnswerService                  
        | onNext               | INFO     | Appending ' the'
        19/12/2023 08:51:57.979 | DocsAnswerService                  
        | onNext               | INFO     | Appending ' first'
        19/12/2023 08:51:57.979 | DocsAnswerService                  
        | onNext               | INFO     | Appending ' and'

        But even when collecting this pieces of text to e.g. minimum
        255 characters to reduce the number of TextArea changes,
        errors happen. So it's not clear how to prevent this as I
        can't define the threshold to be used...

        Dummy code causing the crash:

        public class SearchAction {
            private final StringProperty answer;
            ...
            public StringProperty getAnswerProperty() {
                return answer;
            }

            public void appendAnswer(String token) {
        this.answer.set(this.answer.getValue() + token);
            }
        }

        TextArea lastAnswer = new TextArea();
        lastAnswer.textProperty().bind(searchAction.getAnswerProperty());

        StreamingResponseHandler<AiMessage> streamingResponseHandler =
        new StreamingResponseHandler<>() {
                    @Override
                    public void onNext(String token) {
        searchAction.appendAnswer(token);
                    }
        }

        *Fatal Error *

        #
        # A fatal error has been detected by the Java Runtime Environment:
        #
        #  SIGBUS (0xa) at pc=0x000000013f53b630, pid=13013, tid=80715
        #
        # JRE version: OpenJDK Runtime Environment Zulu21.30+15-CA
        (21.0.1+12) (build 21.0.1+12-LTS)
        # Java VM: OpenJDK 64-Bit Server VM Zulu21.30+15-CA
        (21.0.1+12-LTS, mixed mode, sharing, tiered, compressed oops,
        compressed class ptrs, g1 gc, bsd-aarch64)
        # Problematic frame:
        # j
        
javafx.scene.text.Text.queryAccessibleAttribute(Ljavafx/scene/AccessibleAttribute;[Ljava/lang/Object;)Ljava/lang/Object;+576
        javafx.graphics@21.0.1
        #
        # No core dump will be written. Core dumps have been disabled.
        To enable core dumping, try "ulimit -c unlimited" before
        starting Java again
        #
        # An error report file with more information is saved as:
        # /Users/frankdelporte/GitLab/docs-langchain4j/hs_err_pid13013.log
        Exception in thread "JavaFX Application Thread"
        java.lang.StackOverflowError: Delayed StackOverflowError due
        to ReservedStackAccess annotated method
        at
        
javafx.graphics/com.sun.glass.ui.mac.MacAccessible.NSAccessibilityPostNotification(Native
        Method)
        at
        
javafx.graphics/com.sun.glass.ui.mac.MacAccessible.sendNotification(MacAccessible.java:816)
        at
        
javafx.graphics/javafx.scene.Node.notifyAccessibleAttributeChanged(Node.java:10004)
        at
        
javafx.graphics/javafx.scene.text.Text$TextAttribute$12.invalidated(Text.java:1847)
        at
        
javafx.base/javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:113)
        at
        
javafx.base/javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:148)
        at
        javafx.graphics/javafx.scene.text.Text.setCaretPosition(Text.java:961)
        at
        javafx.graphics/javafx.scene.text.Text$3.invalidated(Text.java:466)
        at
        
javafx.base/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
        at
        
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)
        at
        
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)
        at javafx.graphics/javafx.scene.text.Text.setText(Text.java:444)
        at
        
javafx.controls/javafx.scene.control.skin.TextAreaSkin.lambda$new$16(TextAreaSkin.java:347)
        at
        
javafx.controls/com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler.lambda$new$2(LambdaMultiplePropertyChangeListenerHandler.java:95)
        at
        
javafx.base/javafx.beans.WeakInvalidationListener.invalidated(WeakInvalidationListener.java:82)
        at
        
javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)
        at
        
javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)
        at
        
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1496)
        at
        
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1500)
        at
        
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.controlContentHasChanged(TextInputControl.java:1439)
        at
        
javafx.controls/javafx.scene.control.TextInputControl.lambda$new$0(TextInputControl.java:176)
        at
        
javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:147)
        at
        
javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)
        at
        
javafx.controls/javafx.scene.control.TextInputControl$ContentBase.fireValueChangedEvent(TextInputControl.java:149)
        at
        
javafx.controls/javafx.scene.control.TextArea$TextAreaContent.insert(TextArea.java:214)
        at
        
javafx.controls/javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:1301)
        at
        
javafx.controls/javafx.scene.control.TextInputControl.filterAndSet(TextInputControl.java:1266)
        at
        
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.doSet(TextInputControl.java:1517)
        at
        
javafx.controls/javafx.scene.control.TextInputControl$TextProperty$Listener.invalidated(TextInputControl.java:1540)
        at
        
javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)
        at
        
javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)
        at
        
javafx.base/javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:104)
        at
        
javafx.base/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:111)
        at
        
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)
        at
        
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)
        at
        
com.azul.docs.langchain4j.SearchAction.appendAnswer(SearchAction.java:45)
        at
        
com.azul.docs.langchain4j.DocsAnswerService$2.onNext(DocsAnswerService.java:172)
        at
        
dev.langchain4j.model.openai.OpenAiStreamingChatModel.handle(OpenAiStreamingChatModel.java:152)
        at
        
dev.langchain4j.model.openai.OpenAiStreamingChatModel.lambda$generate$0(OpenAiStreamingChatModel.java:133)
        at
        
dev.ai4j.openai4j.StreamingRequestExecutor$2.onEvent(StreamingRequestExecutor.java:178)
        at
        okhttp3.internal.sse.RealEventSource.onEvent(RealEventSource.kt:101)
        at
        
okhttp3.internal.sse.ServerSentEventReader.completeEvent(ServerSentEventReader.kt:108)
        at
        
okhttp3.internal.sse.ServerSentEventReader.processNextEvent(ServerSentEventReader.kt:52)
        at
        
okhttp3.internal.sse.RealEventSource.processResponse(RealEventSource.kt:75)
        at
        okhttp3.internal.sse.RealEventSource.onResponse(RealEventSource.kt:46)
        at
        okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
        at
        
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at
        
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)
        [93.499s][warning][os] Loading hsdis library failed
        #
        # If you would like to submit a bug report, please visit:
        # http://www.azul.com/support/
        # The crash happened outside the Java Virtual Machine in
        native code.
        # See problematic frame for where to report the bug.
        #

        Process finished with exit code 134 (interrupted by signal
        6:SIGABRT)

        *Error #1*

        Exception in thread "JavaFX Application Thread"
        java.lang.NullPointerException: Cannot read field "advances"
        because "this.layoutCache" is null
        at
        
javafx.graphics/com.sun.javafx.text.PrismTextLayout.shape(PrismTextLayout.java:919)
        at
        
javafx.graphics/com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1113)
        at
        
javafx.graphics/com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:230)
        at
        
javafx.graphics/com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:256)
        at
        javafx.graphics/javafx.scene.text.Text.getLogicalBounds(Text.java:432)
        at
        
javafx.graphics/javafx.scene.text.Text.doComputeGeomBounds(Text.java:1186)
        at
        
javafx.graphics/javafx.scene.text.Text$1.doComputeGeomBounds(Text.java:149)
        at
        
javafx.graphics/com.sun.javafx.scene.shape.TextHelper.computeGeomBoundsImpl(TextHelper.java:90)
        at
        
javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
        at
        javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3812)
        at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3774)
        at
        javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3722)
        at
        
javafx.graphics/javafx.scene.Node$MiscProperties$3.computeBounds(Node.java:6812)
        at
        javafx.graphics/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9749)
        at
        javafx.graphics/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9740)
        at
        javafx.graphics/javafx.scene.Node.getBoundsInLocal(Node.java:3402)
        at
        
javafx.controls/javafx.scene.control.skin.TextAreaSkin$ContentView.layoutChildren(TextAreaSkin.java:1325)
        at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1208)
        at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)
        at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)
        at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)
        at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)
        at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)
        at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)
        at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:594)
        at
        
javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2600)
        at
        
javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:401)
        at
        
java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
        at
        javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:400)
        at
        javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:430)
        at
        
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:592)
        at
        
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:572)
        at
        
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:565)
        at
        
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:352)
        at
        
javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

        *Error #2*

        Exception in thread "JavaFX Application Thread"
        java.lang.NullPointerException: Cannot read the array length
        because "this.lines" is null
        at
        
javafx.graphics/com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1316)
        at
        
javafx.graphics/com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:230)
        at
        
javafx.graphics/com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:256)
        at
        javafx.graphics/javafx.scene.text.Text.getLogicalBounds(Text.java:432)
        at
        
javafx.graphics/javafx.scene.text.Text.doComputeGeomBounds(Text.java:1186)
        at
        
javafx.graphics/javafx.scene.text.Text$1.doComputeGeomBounds(Text.java:149)
        at
        
javafx.graphics/com.sun.javafx.scene.shape.TextHelper.computeGeomBoundsImpl(TextHelper.java:90)
        at
        
javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
        at
        javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3812)
        at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3774)
        at
        javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3722)
        at
        javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3876)
        at
        javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3668)
        at javafx.graphics/javafx.scene.Node.updateBounds(Node.java:776)
        at
        javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)
        at
        javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)
        at
        javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)
        at
        javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)
        at
        javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)
        at
        javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)
        at
        javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)
        at
        javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)
        at
        
javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2615)
        at
        
javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:401)
        at
        
java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
        at
        javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:400)
        at
        javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:430)
        at
        
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:592)
        at
        
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:572)
        at
        
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:565)
        at
        
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:352)
        at
        
javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

        Best regards
        Frank Delporte

        /Want to have coding-fun? /
        /Check my blog //https://webtechie.be//
        <https://webtechie.be/>/and book "Getting started with Java on
        Raspberry Pi" on //https://webtechie.be/books//
        <https://webtechie.be/books/>







Reply via email to