<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>FX doesn't always warn you (as it would mean putting thread
checks everywhere).<br>
</p>
<p>The first trace however shows that the change to the TextArea did
not originate from the FX thread.</p>
<p>--John<br>
</p>
<div class="moz-cite-prefix">On 19/12/2023 18:17, Frank Delporte
wrote:<br>
</div>
<blockquote type="cite"
cite="mid:18c8314b64e.c1e70e00230532.9135748538095378174@webtechie.be">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<div style="font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;">
<div>Thanks John, quick test with this change indeed seems to
solve the problem!<br>
</div>
<pre>Platform.runLater(() -> searchAction.appendAnswer(token));
</pre>
<div>I totally missed this and I didn't notice anything in the
logs that was pointing in this direction.<br>
</div>
<div><br>
</div>
<div id="Zm-_Id_-Sgn" data-sigid="2835100000000004003"
data-zbluepencil-ignore="true">
<div>Best regards<br>
</div>
<div>Frank Delporte<br>
</div>
<div>
<div><br>
</div>
</div>
<div><i>Want to have coding-fun? </i><br>
</div>
<div><i>Check my blog </i><a target="_blank"
href="https://webtechie.be/" moz-do-not-send="true"><i>https://webtechie.be/</i></a><i>
and book "Getting started with Java on Raspberry Pi" on </i><a
target="_blank" href="https://webtechie.be/books/"
moz-do-not-send="true"><i>https://webtechie.be/books/</i></a><br>
</div>
<div>
<div><br>
</div>
</div>
<div><br>
</div>
</div>
<div><br>
</div>
<div class="zmail_extra_hr" style="border-top: 1px solid
rgb(204, 204, 204); height: 0px; margin-top: 10px;
margin-bottom: 10px; line-height: 0px;"><br>
</div>
<div class="zmail_extra" data-zbluepencil-ignore="true">
<div><br>
</div>
<div id="Zm-_Id_-Sgn1">---- On Tue, 19 Dec 2023 09:14:51 +0100
<b>Frank Delporte <a class="moz-txt-link-rfc2396E" href="mailto:frank@webtechie.be"><frank@webtechie.be></a></b> wrote ---<br>
</div>
<div><br>
</div>
<blockquote style="margin: 0px;" id="blockquote_zmail">
<div>
<div style="font-family : Verdana, Arial, Helvetica,
sans-serif; font-size : 10pt;">
<div class="x_1708260380zmail_extra">
<blockquote style="margin : 0px;"
id="x_1708260380blockquote_zmail">
<div>
<div style="font-family : Verdana, Arial,
Helvetica, sans-serif; font-size : 10pt;">
<div>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:<br>
</div>
<div><br>
</div>
<div>19/12/2023 08:51:57.874 |
DocsAnswerService |
onNext | INFO | Appending '
better'<br>
</div>
<div>19/12/2023 08:51:57.874 |
DocsAnswerService |
onNext | INFO | Appending '
performance'<br>
</div>
<div>19/12/2023 08:51:57.875 |
DocsAnswerService |
onNext | INFO | Appending '
after'<br>
</div>
<div>19/12/2023 08:51:57.978 |
DocsAnswerService |
onNext | INFO | Appending '
the'<br>
</div>
<div>19/12/2023 08:51:57.979 |
DocsAnswerService |
onNext | INFO | Appending '
first'<br>
</div>
<div>19/12/2023 08:51:57.979 |
DocsAnswerService |
onNext | INFO | Appending '
and'<br>
</div>
<div><br>
</div>
<div>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...<br>
</div>
<div><br>
</div>
<div>Dummy code causing the crash:<br>
</div>
<div><br>
</div>
<div>public class SearchAction {<br>
</div>
<div> private final StringProperty answer;<br>
</div>
<div> ...<br>
</div>
<div> public StringProperty
getAnswerProperty() {<br>
</div>
<div> return answer;<br>
</div>
<div> }<br>
</div>
<div><br>
</div>
<div> public void appendAnswer(String token)
{<br>
</div>
<div>
this.answer.set(this.answer.getValue() +
token);<br>
</div>
<div> }<br>
</div>
<div>}<br>
</div>
<div><br>
</div>
<div>TextArea lastAnswer = new TextArea();<br>
</div>
<div>lastAnswer.textProperty().bind(searchAction.getAnswerProperty());<br>
</div>
<div><br>
</div>
<div>StreamingResponseHandler<AiMessage>
streamingResponseHandler = new
StreamingResponseHandler<>() {<br>
</div>
<div> @Override<br>
</div>
<div> public void onNext(String
token) {<br>
</div>
<div>
searchAction.appendAnswer(token);<br>
</div>
<div> }<br>
</div>
<div>}<br>
</div>
<div><br>
</div>
<div><b>Fatal Error </b><br>
</div>
<div><br>
</div>
<div>#<br>
</div>
<div># A fatal error has been detected by the
Java Runtime Environment:<br>
</div>
<div>#<br>
</div>
<div># SIGBUS (0xa) at pc=0x000000013f53b630,
pid=13013, tid=80715<br>
</div>
<div>#<br>
</div>
<div># JRE version: OpenJDK Runtime Environment
Zulu21.30+15-CA (21.0.1+12) (build
21.0.1+12-LTS)<br>
</div>
<div># 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)<br>
</div>
<div># Problematic frame:<br>
</div>
<div># j
javafx.scene.text.Text.queryAccessibleAttribute(Ljavafx/scene/AccessibleAttribute;[Ljava/lang/Object;)Ljava/lang/Object;+576
<a class="moz-txt-link-abbreviated" href="mailto:javafx.graphics@21.0.1">javafx.graphics@21.0.1</a><br>
</div>
<div>#<br>
</div>
<div># No core dump will be written. Core dumps
have been disabled. To enable core dumping,
try "ulimit -c unlimited" before starting Java
again<br>
</div>
<div>#<br>
</div>
<div># An error report file with more
information is saved as:<br>
</div>
<div>#
/Users/frankdelporte/GitLab/docs-langchain4j/hs_err_pid13013.log<br>
</div>
<div>Exception in thread "JavaFX Application
Thread" java.lang.StackOverflowError: Delayed
StackOverflowError due to ReservedStackAccess
annotated method<br>
</div>
<div>at
javafx.graphics/com.sun.glass.ui.mac.MacAccessible.NSAccessibilityPostNotification(Native
Method)<br>
</div>
<div>at
javafx.graphics/com.sun.glass.ui.mac.MacAccessible.sendNotification(MacAccessible.java:816)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.notifyAccessibleAttributeChanged(Node.java:10004)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text$TextAttribute$12.invalidated(Text.java:1847)<br>
</div>
<div>at
javafx.base/javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:113)<br>
</div>
<div>at
javafx.base/javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:148)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text.setCaretPosition(Text.java:961)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text$3.invalidated(Text.java:466)<br>
</div>
<div>at
javafx.base/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)<br>
</div>
<div>at
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)<br>
</div>
<div>at
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text.setText(Text.java:444)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.skin.TextAreaSkin.lambda$new$16(TextAreaSkin.java:347)<br>
</div>
<div>at
javafx.controls/com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler.lambda$new$2(LambdaMultiplePropertyChangeListenerHandler.java:95)<br>
</div>
<div>at
javafx.base/javafx.beans.WeakInvalidationListener.invalidated(WeakInvalidationListener.java:82)<br>
</div>
<div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)<br>
</div>
<div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1496)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1500)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.controlContentHasChanged(TextInputControl.java:1439)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextInputControl.lambda$new$0(TextInputControl.java:176)<br>
</div>
<div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:147)<br>
</div>
<div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextInputControl$ContentBase.fireValueChangedEvent(TextInputControl.java:149)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextArea$TextAreaContent.insert(TextArea.java:214)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:1301)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextInputControl.filterAndSet(TextInputControl.java:1266)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty.doSet(TextInputControl.java:1517)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.TextInputControl$TextProperty$Listener.invalidated(TextInputControl.java:1540)<br>
</div>
<div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)<br>
</div>
<div>at
javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)<br>
</div>
<div>at
javafx.base/javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:104)<br>
</div>
<div>at
javafx.base/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:111)<br>
</div>
<div>at
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)<br>
</div>
<div>at
javafx.base/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)<br>
</div>
<div>at
com.azul.docs.langchain4j.SearchAction.appendAnswer(SearchAction.java:45)<br>
</div>
<div>at
com.azul.docs.langchain4j.DocsAnswerService$2.onNext(DocsAnswerService.java:172)<br>
</div>
<div>at
dev.langchain4j.model.openai.OpenAiStreamingChatModel.handle(OpenAiStreamingChatModel.java:152)<br>
</div>
<div>at
dev.langchain4j.model.openai.OpenAiStreamingChatModel.lambda$generate$0(OpenAiStreamingChatModel.java:133)<br>
</div>
<div>at
dev.ai4j.openai4j.StreamingRequestExecutor$2.onEvent(StreamingRequestExecutor.java:178)<br>
</div>
<div>at
okhttp3.internal.sse.RealEventSource.onEvent(RealEventSource.kt:101)<br>
</div>
<div>at
okhttp3.internal.sse.ServerSentEventReader.completeEvent(ServerSentEventReader.kt:108)<br>
</div>
<div>at
okhttp3.internal.sse.ServerSentEventReader.processNextEvent(ServerSentEventReader.kt:52)<br>
</div>
<div>at
okhttp3.internal.sse.RealEventSource.processResponse(RealEventSource.kt:75)<br>
</div>
<div>at
okhttp3.internal.sse.RealEventSource.onResponse(RealEventSource.kt:46)<br>
</div>
<div>at
okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)<br>
</div>
<div>at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)<br>
</div>
<div>at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)<br>
</div>
<div>at
java.base/java.lang.Thread.run(Thread.java:1583)<br>
</div>
<div>[93.499s][warning][os] Loading hsdis
library failed<br>
</div>
<div>#<br>
</div>
<div># If you would like to submit a bug report,
please visit:<br>
</div>
<div># <a target="_blank"
href="http://www.azul.com/support/"
moz-do-not-send="true"
class="moz-txt-link-freetext">http://www.azul.com/support/</a><br>
</div>
<div># The crash happened outside the Java
Virtual Machine in native code.<br>
</div>
<div># See problematic frame for where to report
the bug.<br>
</div>
<div>#<br>
</div>
<div><br>
</div>
<div>Process finished with exit code 134
(interrupted by signal 6:SIGABRT)<br>
</div>
<div><br>
</div>
<div><b>Error #1</b><br>
</div>
<div><br>
</div>
<div>Exception in thread "JavaFX Application
Thread" java.lang.NullPointerException: Cannot
read field "advances" because
"this.layoutCache" is null<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.shape(PrismTextLayout.java:919)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1113)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:230)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:256)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text.getLogicalBounds(Text.java:432)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text.doComputeGeomBounds(Text.java:1186)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text$1.doComputeGeomBounds(Text.java:149)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.scene.shape.TextHelper.computeGeomBoundsImpl(TextHelper.java:90)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3812)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3774)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3722)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node$MiscProperties$3.computeBounds(Node.java:6812)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9749)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9740)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.getBoundsInLocal(Node.java:3402)<br>
</div>
<div>at
javafx.controls/javafx.scene.control.skin.TextAreaSkin$ContentView.layoutChildren(TextAreaSkin.java:1325)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.layout(Parent.java:1208)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.layout(Parent.java:1215)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:594)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2600)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:401)<br>
</div>
<div>at
java.base/java.security.AccessController.doPrivileged(AccessController.java:400)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:400)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:430)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:592)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:572)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:565)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:352)<br>
</div>
<div>at
javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)<br>
</div>
<div><br>
</div>
<div><b>Error #2</b><br>
</div>
<div><br>
</div>
<div>Exception in thread "JavaFX Application
Thread" java.lang.NullPointerException: Cannot
read the array length because "this.lines" is
null<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1316)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:230)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:256)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text.getLogicalBounds(Text.java:432)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text.doComputeGeomBounds(Text.java:1186)<br>
</div>
<div>at
javafx.graphics/javafx.scene.text.Text$1.doComputeGeomBounds(Text.java:149)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.scene.shape.TextHelper.computeGeomBoundsImpl(TextHelper.java:90)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3812)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3774)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3722)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3876)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3668)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Node.updateBounds(Node.java:776)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1834)<br>
</div>
<div>at
javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2615)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:401)<br>
</div>
<div>at
java.base/java.security.AccessController.doPrivileged(AccessController.java:400)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:400)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:430)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:592)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:572)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:565)<br>
</div>
<div>at
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:352)<br>
</div>
<div>at
javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)<br>
</div>
<div><br>
</div>
<div class="x_1879826395zmail_signature_below">
<div id="">
<div>Best regards<br>
</div>
<div>Frank Delporte<br>
</div>
<div>
<div><br>
</div>
</div>
<div><i>Want to have coding-fun? </i><br>
</div>
<div><i>Check my blog </i><a target="_blank"
href="https://webtechie.be/"
moz-do-not-send="true"><i>https://webtechie.be/</i></a><i>
and book "Getting started with Java on
Raspberry Pi" on </i><a target="_blank"
href="https://webtechie.be/books/"
moz-do-not-send="true"><i>https://webtechie.be/books/</i></a><br>
</div>
<div>
<div><br>
</div>
</div>
<div><br>
</div>
</div>
</div>
<div><br>
</div>
</div>
<br>
</div>
</blockquote>
</div>
<div><br>
</div>
</div>
<br>
</div>
</blockquote>
</div>
<div><br>
</div>
</div>
<br>
</blockquote>
</body>
</html>