<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Looking at the related issues in the bug tracker, it seems like
one common cause are modifications on a non-platform thread. I
hooked up our application to a detection mechanism, but didn't get
any meaningful hits so far. Maybe I will find something in the
future with this.<br>
<br>
For reference, is there any already existing best practice to
detect these non-platform thread modifications? I just wrote my
own, feel free to check if I'm missing anything:<br>
</p>
<div style="background-color:#1e1f22;color:#bcbec4">
<pre
style="font-family:'JetBrains Mono',monospace;font-size:9,8pt;">
<span style="color:#cf8e6d;">public class </span>NodeCallback {
<span style="color:#cf8e6d;">private static final </span>Set<Window> <span
style="color:#c77dbb;font-style:italic;">windows </span>= <span
style="color:#cf8e6d;">new </span>HashSet<>();
<span style="color:#cf8e6d;">private static final </span>Set<Node> <span
style="color:#c77dbb;font-style:italic;">nodes </span>= <span
style="color:#cf8e6d;">new </span>HashSet<>();
<span style="color:#cf8e6d;">public static void </span><span
style="color:#56a8f5;">init</span>() {
<span style="color:#cf8e6d;">if </span>(!AppProperties.<span
style="font-style:italic;">get</span>().isDebugPlatformThreadAccess()) {
<span style="color:#cf8e6d;">return</span>;
}
Window.<span style="font-style:italic;">getWindows</span>().addListener((ListChangeListener<? <span
style="color:#cf8e6d;">super </span>Window>) change -> {
<span style="color:#cf8e6d;">for </span>(Window window : change.getList()) {
<span style="color:#cf8e6d;">if </span>(!<span
style="color:#c77dbb;font-style:italic;">windows</span>.add(window)) {
<span style="color:#cf8e6d;">continue</span>;
}
window.sceneProperty().subscribe(scene -> {
<span style="color:#cf8e6d;">if </span>(scene == <span
style="color:#cf8e6d;">null</span>) {
<span style="color:#cf8e6d;">return</span>;
}
scene.rootProperty().subscribe(root -> {
<span style="color:#cf8e6d;">if </span>(root != <span
style="color:#cf8e6d;">null</span>) {
<span style="font-style:italic;">watchPlatformThreadChanges</span>(root);
}
});
});
}
});
}
<span style="color:#cf8e6d;">private static void </span><span
style="color:#56a8f5;">watchPlatformThreadChanges</span>(Node node) {
<span style="font-style:italic;">watchGraph</span>(node, c -> {
<span style="color:#cf8e6d;">if </span>(!<span
style="color:#c77dbb;font-style:italic;">nodes</span>.add(c)) {
<span style="color:#cf8e6d;">return</span>;
}
<span style="color:#cf8e6d;">if </span>(c <span
style="color:#cf8e6d;">instanceof </span>Parent p) {
p.getChildrenUnmodifiable().addListener((ListChangeListener<? <span
style="color:#cf8e6d;">super </span>Node>) change -> {
<span style="font-style:italic;">checkPlatformThread</span>();
});
}
c.visibleProperty().addListener((observable, oldValue, newValue) -> {
<span style="font-style:italic;">checkPlatformThread</span>();
});
c.boundsInParentProperty().addListener((observable, oldValue, newValue) -> {
<span style="font-style:italic;">checkPlatformThread</span>();
});
c.managedProperty().addListener((observable, oldValue, newValue) -> {
<span style="font-style:italic;">checkPlatformThread</span>();
});
c.opacityProperty().addListener((observable, oldValue, newValue) -> {
<span style="font-style:italic;">checkPlatformThread</span>();
});
});
}
<span style="color:#cf8e6d;">private static void </span><span
style="color:#56a8f5;">watchGraph</span>(Node node, Consumer<Node> callback) {
<span style="color:#cf8e6d;">if </span>(node <span
style="color:#cf8e6d;">instanceof </span>Parent p) {
<span style="color:#cf8e6d;">for </span>(Node c : p.getChildrenUnmodifiable()) {
<span style="font-style:italic;">watchGraph</span>(c, callback);
}
p.getChildrenUnmodifiable().addListener((ListChangeListener<? <span
style="color:#cf8e6d;">super </span>Node>) change -> {
<span style="color:#cf8e6d;">for </span>(Node c : change.getList()) {
<span style="font-style:italic;">watchGraph</span>(c, <span
style="color:#c77dbb;">callback</span>);
}
});
}
callback.accept(node);
}
<span style="color:#cf8e6d;">private static void </span><span
style="color:#56a8f5;">checkPlatformThread</span>() {
<span style="color:#cf8e6d;">if </span>(!Platform.<span
style="font-style:italic;">isFxApplicationThread</span>()) {
<span style="color:#cf8e6d;">throw new </span>IllegalStateException(<span
style="color:#6aab73;">"Not in Fx application thread"</span>);
}
}
}</pre>
</div>
<div class="moz-cite-prefix">On 28/03/2025 21:06, Martin Fox wrote:<br>
</div>
<blockquote type="cite"
cite="mid:CB995A83-E9E7-497E-815E-5D414368A614@gmail.com">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
This isn’t an area of the code that I’m familiar with. Searching
for updateCachedBounds in the bug database shows that there’s some
history here so maybe someone with more experience can chime in.<br
id="lineBreakAtBeginningOfMessage">
<div><br>
<blockquote type="cite">
<div>On Mar 28, 2025, at 11:06 AM, Christopher Schnick
<a class="moz-txt-link-rfc2396E" href="mailto:crschnick@xpipe.io"><crschnick@xpipe.io></a> wrote:</div>
<br class="Apple-interchange-newline">
<div>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8">
<div>
<p>So I tried various different things to reproduce it
without the StackOverflow, but no success so far. But I
can definitely tell you from many user issue reports
that this issue frequently happens. Looking at the logs
when this happens, there were no other exceptions
reported when this happens.</p>
<p>It however doesn't leave the node in a bad state in
most cases, in production this exception usually only
occurs once without the same exception happening in
later pulses. Having a loop of pulse exceptions that
happened with the JVM crash is rarer. It breaks the
layout however, so a restart is required.</p>
<p>I would already be happy with a simple index check to
not throw an OOB exception in the implementation, I
don't think there's any harm in that. While the
StackOverflow is a very made-up case, I think even for
that it would be good if it wouldn't throw exceptions in
later pulses if you're looking for a justification on
why to implement an index check.<br>
</p>
<div class="moz-cite-prefix">On 28/03/2025 17:26, Martin
Fox wrote:<br>
</div>
<blockquote type="cite"
cite="mid:9F065E4B-F67A-40E2-9D3D-CAF9225CE191@gmail.com">
<meta http-equiv="content-type"
content="text/html; charset=UTF-8">
<div>I’ve been able to reproduce this inside a debugger
on my Mac every eighth try or so.</div>
<div><br>
</div>
<div>I’m not sure what I’m seeing is all that helpful.
Your reproducing case is inducing a stack overflow
exception. If the exception occurs while
Parent.updateCachedBounds is executing the StackPane
will be left in a bad state. This leads to the
dirtyChildrenCount exceeding the number of children
and then Parent.updateCachedBounds will start throwing
the same AIOOBE on every layout pulse.</div>
<div><br>
</div>
<div>At least in my debug runs it’s all about the timing
of the stack overflow. That probably doesn’t explain
why your production app is getting into the same bad
state.</div>
<div><br>
</div>
<div>And you’re right, this has nothing to do with the
Alert. I was confused by the gap between when the
exception occurs and when it’s reported.</div>
<div><br>
</div>
<div>Martin</div>
<div><br>
<blockquote type="cite">
<div>On Mar 26, 2025, at 9:20 PM, Christopher
Schnick <a class="moz-txt-link-rfc2396E"
href="mailto:crschnick@xpipe.io"
moz-do-not-send="true"><crschnick@xpipe.io></a>
wrote:</div>
<br class="Apple-interchange-newline">
<div>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8">
<div>
<p>Interesting, that exception does not happen
on my macOS 15.3 system. The reproducer
somehow also doesn't seem to trigger the
IndexOutOfBoundsExceptions on macOS for me,
only on Windows so far. On Windows, the large
alert is shown as a broken stage with no
content and controls for me, which I guess is
slightly better than an exception, but also
not ideal. So it seems like the reproducer
behavior depends a lot on the specific system.<br>
</p>
<div class="moz-cite-prefix">On 26/03/2025
19:35, Martin Fox wrote:<br>
</div>
<blockquote type="cite"
cite="mid:6532F614-D25B-4C55-9519-4DE1CD8629E0@gmail.com">
<meta http-equiv="content-type"
content="text/html; charset=UTF-8">
Christopher,
<div><br>
</div>
<div>Yes, there might be more than one issue
here. On the Mac the call to
Stage.showAndWait is making its way into the
Mac glass code where an exception is being
thrown leading to another call to
Stage.showAndWait. I’ve attached the
repeating block below. I don’t see that
pattern in the Windows stack trace you
provided.</div>
<div><br>
</div>
<div>Martin</div>
<div><br>
</div>
<div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at
ParentBoundsBug.lambda$start$0(ParentBoundsBug.java:25)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at
java.base/java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:663)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at
java.base/java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:658)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/com.sun.glass.ui.Application.reportException"
moz-do-not-send="true">javafx.graphics@25-internal/com.sun.glass.ui.Application.reportException</a>(Application.java:452)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/com.sun.glass.ui.mac.MacWindow._setBounds2"
moz-do-not-send="true">javafx.graphics@25-internal/com.sun.glass.ui.mac.MacWindow._setBounds2</a>(Native
Method)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/com.sun.glass.ui.mac.MacWindow._setBounds"
moz-do-not-send="true">javafx.graphics@25-internal/com.sun.glass.ui.mac.MacWindow._setBounds</a>(MacWindow.java:70)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/com.sun.glass.ui.Window.setBounds"
moz-do-not-send="true">javafx.graphics@25-internal/com.sun.glass.ui.Window.setBounds</a>(Window.java:589)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/com.sun.javafx.tk.quantum.WindowStage.setBounds"
moz-do-not-send="true">javafx.graphics@25-internal/com.sun.javafx.tk.quantum.WindowStage.setBounds</a>(WindowStage.java:304)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/javafx.stage.Window$TKBoundsConfigurator.apply"
moz-do-not-send="true">javafx.graphics@25-internal/javafx.stage.Window$TKBoundsConfigurator.apply</a>(Window.java:1566)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/javafx.stage.Window.applyBounds"
moz-do-not-send="true">javafx.graphics@25-internal/javafx.stage.Window.applyBounds</a>(Window.java:1424)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/javafx.stage.Window.adjustSize"
moz-do-not-send="true">javafx.graphics@25-internal/javafx.stage.Window.adjustSize</a>(Window.java:327)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/javafx.stage.Window.sizeToScene"
moz-do-not-send="true">javafx.graphics@25-internal/javafx.stage.Window.sizeToScene</a>(Window.java:284)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/javafx.stage.Window$12.invalidated"
moz-do-not-send="true">javafx.graphics@25-internal/javafx.stage.Window$12.invalidated</a>(Window.java:1215)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.base@25-internal/javafx.beans.property.BooleanPropertyBase.markInvalid"
moz-do-not-send="true">javafx.base@25-internal/javafx.beans.property.BooleanPropertyBase.markInvalid</a>(BooleanPropertyBase.java:110)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.base@25-internal/javafx.beans.property.BooleanPropertyBase.set"
moz-do-not-send="true">javafx.base@25-internal/javafx.beans.property.BooleanPropertyBase.set</a>(BooleanPropertyBase.java:145)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/javafx.stage.Window.setShowing"
moz-do-not-send="true">javafx.graphics@25-internal/javafx.stage.Window.setShowing</a>(Window.java:1235)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/javafx.stage.Window.show"
moz-do-not-send="true">javafx.graphics@25-internal/javafx.stage.Window.show</a>(Window.java:1250)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/javafx.stage.Stage.show"
moz-do-not-send="true">javafx.graphics@25-internal/javafx.stage.Stage.show</a>(Stage.java:272)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.graphics@25-internal/javafx.stage.Stage.showAndWait"
moz-do-not-send="true">javafx.graphics@25-internal/javafx.stage.Stage.showAndWait</a>(Stage.java:427)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.controls@25-internal/javafx.scene.control.HeavyweightDialog.showAndWait"
moz-do-not-send="true">javafx.controls@25-internal/javafx.scene.control.HeavyweightDialog.showAndWait</a>(HeavyweightDialog.java:162)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at <a
class="moz-txt-link-abbreviated moz-txt-link-freetext"
href="mailto:javafx.controls@25-internal/javafx.scene.control.Dialog.showAndWait"
moz-do-not-send="true">javafx.controls@25-internal/javafx.scene.control.Dialog.showAndWait</a>(Dialog.java:347)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at
ParentBoundsBug.lambda$start$0(ParentBoundsBug.java:25)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at
java.base/java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:663)</div>
<div><span class="Apple-tab-span"
style="white-space:pre"> </span>at
java.base/java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:658)</div>
</div>
<div><br>
</div>
<div>
<div>
<blockquote type="cite">
<div>On Mar 26, 2025, at 10:49 AM,
Christopher Schnick <a
class="moz-txt-link-rfc2396E"
href="mailto:crschnick@xpipe.io"
moz-do-not-send="true"><crschnick@xpipe.io></a>
wrote:</div>
<br class="Apple-interchange-newline">
<div>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8">
<div>
<p>Hey Martin,<br>
<br>
thank you for looking into this.
The initial StackOverflow is a
result of me forcing to reproduce
the bounds
IndexOutOfBoundsException. The
StackOverflow can be ignored, it
was merely the best method I found
to transition the scene graph into
a state where the
IndexOutOfBoundsExceptions are
thrown. The OOBs are not thrown in
every run though, it sometimes
takes a few tries. In our
production application, the same
IndexOutOfBoundsExceptions also
occur randomly without a previous
exception. You can probably also
reproduce the
IndexOutOfBoundsExceptions without
the StackOverflow, but reproducing
it was very fragile, so I didn't
look into it more.<br>
<br>
I don't think it has necessarily
something to do with the alert
bounds as the
IndexOutOfBoundsException is also
thrown if you don't show an alert
at all. The constant
IndexOutOfBoundsExceptions in
combination with the alert
showAndWait was how our
application entered the original
crashing state. So the reproducer
is more like a two-in-one.<br>
<br>
Best<br>
Christopher Schnick<br>
</p>
<div class="moz-cite-prefix">On
26/03/2025 18:33, Martin Fox
wrote:<br>
</div>
<blockquote type="cite"
cite="mid:9560C9BE-BC2F-4F0D-B914-425969699179@gmail.com">
<meta http-equiv="content-type"
content="text/html; charset=UTF-8">
Yes, thank you Christopher for
providing a reproducible test
case!
<div><br>
</div>
<div>I was able to trigger the
problem on my Mac on the first
try. Since I’m using a modified
version of JavaFX the system
didn’t crash but instead hit a
Java stack overflow error and
produced a very long stack
trace.</div>
<div><br>
</div>
<div>At least on the Mac the
problem seems to be that you’re
trying to pop an Alert
containing a long stack trace.
While trying to adjust the
Alert’s bounds JavaFX is
throwing another exception but
I’m not sure why. I’ll continue
to look into it.</div>
<div><br>
</div>
<div>Thanks again,</div>
<div>Martin</div>
<div>
<div>
<div><br>
<blockquote type="cite">
<div>On Mar 25, 2025, at
12:16 PM, Andy Goryachev
<a
class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"
moz-do-not-send="true"><andy.goryachev@oracle.com></a>
wrote:</div>
<br
class="Apple-interchange-newline">
<div>
<meta charset="UTF-8">
<div
class="WordSection1"
style="page: WordSection1; caret-color: rgb(0, 0, 0); font-family: Optima-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">Thank
you, Christopher,
for clarification!<o:p></o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"><o:p> </o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">Personally,
I would consider
this to be a
problem with the
application
design: the code
should limit the
number of alerts
shown to the
user. Do you
really want the
user to click
through hundreds
of alerts?<o:p></o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"><o:p> </o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">Nevertheless,
you are right
about the need for
the platform to
gracefully handle
the case of too
many nested event
loops - by
throwing an
exception with a
meaningful
message, as Martin
proposed in<span
class="Apple-converted-space"> </span><a
href="https://github.com/openjdk/jfx/pull/1741"
style="color: blue; text-decoration: underline;" moz-do-not-send="true"
class="moz-txt-link-freetext">https://github.com/openjdk/jfx/pull/1741</a><o:p></o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"><o:p> </o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">Cheers,<o:p></o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">-andy<o:p></o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"><o:p> </o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"><o:p> </o:p></span></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"><o:p> </o:p></span></div>
<div
id="mail-editor-reference-message-container">
<div>
<div>
<div
style="border-width: 1pt medium medium; border-style: solid none none; border-color: rgb(181, 196, 223) currentcolor currentcolor; border-image: none; padding: 3pt 0in 0in;">
<p
class="MsoNormal"
style="margin: 0in 0in 12pt; font-size: 10pt; font-family: Aptos, sans-serif;"><b><span
style="font-size: 12pt;">From:<span class="Apple-converted-space"> </span></span></b><span
style="font-size: 12pt;">Christopher Schnick <a
class="moz-txt-link-rfc2396E" href="mailto:crschnick@xpipe.io"
moz-do-not-send="true"><crschnick@xpipe.io></a><br>
<b>Date:<span
class="Apple-converted-space"> </span></b>Tuesday, March 25, 2025 at
11:52<br>
<b>To:<span
class="Apple-converted-space"> </span></b>Andy Goryachev <a
class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"
moz-do-not-send="true"><andy.goryachev@oracle.com></a><br>
<b>Cc:<span
class="Apple-converted-space"> </span></b>OpenJFX <a
class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true"><openjfx-dev@openjdk.org></a><br>
<b>Subject:<span
class="Apple-converted-space"> </span></b>Re: [External] : Re: JVM
crashes on
macOS when
entering too
many nested
event loops<o:p></o:p></span></p>
</div>
<p>Hey Andy,<br>
<br>
so I think I
was able to
reproduce this
issue for our
application.<br>
<br>
There are two
main factors
how this can
happen:<br>
- We use an
alert-based
error
reporter,
meaning that
we have a
default
uncaught
exception
handler set
for all
threads which
will
showAndWait an
Alert with the
exception
message<br>
- As I
reported
yesterday with<span
class="Apple-converted-space"> </span><a
href="https://mail.openjdk.org/pipermail/openjfx-dev/2025-March/052963.html"
style="color: blue; text-decoration: underline;" moz-do-not-send="true"
class="moz-txt-link-freetext">https://mail.openjdk.org/pipermail/openjfx-dev/2025-March/052963.html</a>,
there are some
rare
exceptions
that can occur
in a normal
event loop
without
interference
of the
application,
probably
because of a
small bug in
the bounds
calculation
code<br>
<br>
If you combine
these two
factors, you
will end up
with an
infinite loop
of the
showAndWait
entering a
nested event
loop, the
event loop
throwing an
internal
exception, and
the uncaught
exception
handler
starting the
same loop with
another alert.
I don't think
this is a bad
implementation
from our side,
the only thing
that we can
improve is to
maybe check
how deep the
uncaught
exception loop
is in to
prevent this
from occurring
indefinitely.
But I would
argue this can
happen to any
application.
Here is a
sample code,
based on the
reproducer
from the
OutOfBounds
report from
yesterday:<o:p></o:p></p>
<div>
<pre
style="margin: 0in; font-size: 8pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">javafx.application.Application;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">javafx.application.Platform;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">javafx.scene.Scene;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">javafx.scene.control.Alert;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">javafx.scene.control.Button;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">javafx.scene.layout.Region;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">javafx.scene.layout.StackPane;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">javafx.scene.layout.VBox;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">javafx.stage.Stage;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"><o:p> </o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">java.io.IOException;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">import </span><span
style="color: rgb(188, 190, 196);">java.util.Arrays;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"><o:p> </o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(207, 142, 109);">public class </span><span
style="color: rgb(188, 190, 196);">ParentBoundsBug </span><span
style="color: rgb(207, 142, 109);">extends </span><span
style="color: rgb(188, 190, 196);">Application {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"><o:p> </o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(179, 174, 96);">@Override<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(179, 174, 96);"> </span><span
style="color: rgb(207, 142, 109);">public void </span><span
style="color: rgb(86, 168, 245);">start</span><span
style="color: rgb(188, 190, 196);">(Stage stage) </span><span
style="color: rgb(207, 142, 109);">throws </span><span
style="color: rgb(188, 190, 196);">IOException {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> Thread.<i>setDefaultUncaughtExceptionHandler</i>((thread, throwable) -> {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> throwable.printStackTrace();<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"><o:p> </o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(207, 142, 109);">if </span><span
style="color: rgb(188, 190, 196);">(Platform.<i>isFxApplicationThread</i>()) {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(207, 142, 109);">var </span><span
style="color: rgb(188, 190, 196);">alert = </span><span
style="color: rgb(207, 142, 109);">new </span><span
style="color: rgb(188, 190, 196);">Alert(Alert.AlertType.</span><i><span
style="color: rgb(199, 125, 187);">ERROR</span></i><span
style="color: rgb(188, 190, 196);">);<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> alert.setHeaderText(throwable.getMessage());<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> alert.setContentText(Arrays.<i>toString</i>(throwable.getStackTrace()));<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> alert.showAndWait();<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> } </span><span
style="color: rgb(207, 142, 109);">else </span><span
style="color: rgb(188, 190, 196);">{<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(122, 126, 133);">// Do some other error handling for non-platform threads<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(122, 126, 133);"> // Probably just show the alert with a runLater()<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(122, 126, 133);"><o:p> </o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(122, 126, 133);"> // For this example, there are no exceptions outside the platform thread<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(122, 126, 133);"> </span><span
style="color: rgb(188, 190, 196);">}<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> });<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"><o:p> </o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(122, 126, 133);">// Run delayed as Application::reportException will only be called for exceptions<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(122, 126, 133);"> // after the application has started<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(122, 126, 133);"> </span><span
style="color: rgb(188, 190, 196);">Platform.<i>runLater</i>(() -> {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> Scene scene = </span><span
style="color: rgb(207, 142, 109);">new </span><span
style="color: rgb(188, 190, 196);">Scene(createContent(), </span><span
style="color: rgb(42, 172, 184);">640</span><span
style="color: rgb(188, 190, 196);">, </span><span
style="color: rgb(42, 172, 184);">480</span><span
style="color: rgb(188, 190, 196);">);<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(199, 125, 187);">stage</span><span
style="color: rgb(188, 190, 196);">.setScene(scene);<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(199, 125, 187);">stage</span><span
style="color: rgb(188, 190, 196);">.show();<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(199, 125, 187);">stage</span><span
style="color: rgb(188, 190, 196);">.centerOnScreen();<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> });<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> }<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"><o:p> </o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(207, 142, 109);">private </span><span
style="color: rgb(188, 190, 196);">Region </span><span
style="color: rgb(86, 168, 245);">createContent</span><span
style="color: rgb(188, 190, 196);">() {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(207, 142, 109);">var </span><span
style="color: rgb(188, 190, 196);">b1 = </span><span
style="color: rgb(207, 142, 109);">new </span><span
style="color: rgb(188, 190, 196);">Button(</span><span
style="color: rgb(106, 171, 115);">"Click me!"</span><span
style="color: rgb(188, 190, 196);">);<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(207, 142, 109);">var </span><span
style="color: rgb(188, 190, 196);">b2 = </span><span
style="color: rgb(207, 142, 109);">new </span><span
style="color: rgb(188, 190, 196);">Button(</span><span
style="color: rgb(106, 171, 115);">"Click me!"</span><span
style="color: rgb(188, 190, 196);">);<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(207, 142, 109);">var </span><span
style="color: rgb(188, 190, 196);">vbox = </span><span
style="color: rgb(207, 142, 109);">new </span><span
style="color: rgb(188, 190, 196);">VBox(b1, b2);<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> b1.boundsInParentProperty().addListener((observable, oldValue, newValue) -> {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(199, 125, 187);">vbox</span><span
style="color: rgb(188, 190, 196);">.setVisible(!</span><span
style="color: rgb(199, 125, 187);">vbox</span><span
style="color: rgb(188, 190, 196);">.isVisible());<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> });<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> b2.boundsInParentProperty().addListener((observable, oldValue, newValue) -> {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(199, 125, 187);">vbox</span><span
style="color: rgb(188, 190, 196);">.setVisible(!</span><span
style="color: rgb(199, 125, 187);">vbox</span><span
style="color: rgb(188, 190, 196);">.isVisible());<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> });<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> vbox.boundsInParentProperty().addListener((observable, oldValue, newValue) -> {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(199, 125, 187);">vbox</span><span
style="color: rgb(188, 190, 196);">.setVisible(!</span><span
style="color: rgb(199, 125, 187);">vbox</span><span
style="color: rgb(188, 190, 196);">.isVisible());<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> });<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"><o:p> </o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(207, 142, 109);">var </span><span
style="color: rgb(188, 190, 196);">stack = </span><span
style="color: rgb(207, 142, 109);">new </span><span
style="color: rgb(188, 190, 196);">StackPane(vbox, </span><span
style="color: rgb(207, 142, 109);">new </span><span
style="color: rgb(188, 190, 196);">StackPane());<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> stack.boundsInParentProperty().addListener((observable, oldValue, newValue) -> {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(199, 125, 187);">vbox</span><span
style="color: rgb(188, 190, 196);">.setVisible(!</span><span
style="color: rgb(199, 125, 187);">vbox</span><span
style="color: rgb(188, 190, 196);">.isVisible());<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> });<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(207, 142, 109);">return </span><span
style="color: rgb(188, 190, 196);">stack;<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> }<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"><o:p> </o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> </span><span
style="color: rgb(207, 142, 109);">public static void </span><span
style="color: rgb(86, 168, 245);">main</span><span
style="color: rgb(188, 190, 196);">(String[] args) {<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> <i>launch</i>();<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);"> }<o:p></o:p></span></pre>
<pre
style="margin: 0in; font-size: 10pt; font-family: "Courier New"; background: rgb(30, 31, 34);"><span
style="color: rgb(188, 190, 196);">}<o:p></o:p></span></pre>
</div>
<p><br>
If the same
OutOfBounds
exception from
the reported I
linked happens
in the bounds
calculation,
which happens
approximately
1/5 runs for
me, this
application
will enter new
event loops
until it
crashes. If
the
OutOfBounds
doesn't
trigger, it
will just
throw a
StackOverflow
but won't
continue the
infinite loop
of nested
event loops.
So for the
reproducer it
is important
to try a few
times until
you get the
described
OutOfBounds.<o:p></o:p></p>
<p>I attached
the stacktrace
of how this
fails. The
initial
StackOverflow
causes
infinitely
many following
exceptions in
the nested
event loop.<o:p></o:p></p>
<p>Best<br>
Christopher
Schnick<o:p></o:p></p>
<div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 12pt;">On 25/03/2025 18:28, Andy Goryachev wrote:<o:p></o:p></span></div>
</div>
<blockquote
style="margin-top: 5pt; margin-bottom: 5pt;">
<div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">Dear
Christopher:</span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">Were
you able to
root cause why
your
application
enters that
many nested
event loops?</span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">I
believe a
well-behaved
application
should never
experience
that, unless
there is some
design flaw or
a bug.</span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">-andy</span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
id="mail-editor-reference-message-container">
<div>
<div>
<div
style="border-width: 1pt medium medium; border-style: solid none none; border-color: rgb(181, 196, 223) currentcolor currentcolor; border-image: none; padding: 3pt 0in 0in;">
<p
class="MsoNormal"
style="margin: 0in 0in 12pt; font-size: 10pt; font-family: Aptos, sans-serif;"><b><span
style="font-size: 12pt;">From:<span class="Apple-converted-space"> </span></span></b><span
style="font-size: 12pt;">Christopher Schnick<span
class="Apple-converted-space"> </span><a
href="mailto:crschnick@xpipe.io"
style="color: blue; text-decoration: underline;" moz-do-not-send="true"><crschnick@xpipe.io></a><br>
<b>Date:<span
class="Apple-converted-space"> </span></b>Monday, March 10, 2025 at
19:45<br>
<b>To:<span
class="Apple-converted-space"> </span></b>Andy Goryachev<span
class="Apple-converted-space"> </span><a
href="mailto:andy.goryachev@oracle.com"
style="color: blue; text-decoration: underline;" moz-do-not-send="true"><andy.goryachev@oracle.com></a><br>
<b>Subject:<span
class="Apple-converted-space"> </span></b>[External] : Re: JVM crashes
on macOS when
entering too
many nested
event loops</span><o:p></o:p></p>
</div>
<p>Our code
and some
libraries do
enter some
nested event
loops at a few
places when it
makes sense,
but we didn't
do anything to
explicitly
provoke this,
this occurred
naturally in
our
application.
So it would be
nice if JavaFX
could somehow
guard against
this,
especially
since crashing
the JVM is
probably the
worst thing
that can
happen.<br>
<br>
I looked at
the
documentation,
but it seems
like the
public API at
Platform::enterNestedEventLoop does not mention this.<br>
From my
understanding,
the method
Platform::canStartNestedEventLoop
is potentially
the right
method to
indicate to
the caller
that the limit
is close by
returning
false.<br>
And even if
something like
an exception
is thrown when
a nested event
loop is
started while
it is close to
the limit,
that would
still be much
better than a
direct crash.<br>
<br>
Best<br>
Christopher
Schnick<o:p></o:p></p>
<div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 12pt;">On 10/03/2025 18:51, Andy Goryachev wrote:</span><o:p></o:p></div>
</div>
<blockquote
style="margin-top: 5pt; margin-bottom: 5pt;">
<div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">This
looks to me
like it might
be hitting the
(native)
thread stack
size limit.</span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">c.s.glass.ui.Application::enterNestedEventLoop()
even warns
about it:</span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; background: white;"><span
style="font-family: "Iosevka Fixed SS16"; color: rgb(255, 38, 0);">
* An
application
may enter
several nested
loops
recursively.
There's no</span><o:p></o:p></div>
<div
style="margin: 0in; background: white;"><span
style="font-family: "Iosevka Fixed SS16"; color: rgb(255, 38, 0);">
* limit of
recursion
other than
that imposed
by the native
stack size.</span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";">-andy</span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
style="margin: 0in; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt; font-family: "Iosevka Fixed SS16";"> </span><o:p></o:p></div>
<div
id="mail-editor-reference-message-container">
<div>
<div>
<div
style="border-width: 1pt medium medium; border-style: solid none none; border-color: rgb(181, 196, 223) currentcolor currentcolor; border-image: none; padding: 3pt 0in 0in;">
<p
class="MsoNormal"
style="margin: 0in 0in 12pt; font-size: 10pt; font-family: Aptos, sans-serif;"><b><span
style="font-size: 12pt;">From:<span class="Apple-converted-space"> </span></span></b><span
style="font-size: 12pt;">openjfx-dev<span class="Apple-converted-space"> </span><a
href="mailto:openjfx-dev-retn@openjdk.org"
style="color: blue; text-decoration: underline;" moz-do-not-send="true"><openjfx-dev-retn@openjdk.org></a><span
class="Apple-converted-space"> </span>on behalf of Martin Fox<span
class="Apple-converted-space"> </span><a
href="mailto:martinfox656@gmail.com"
style="color: blue; text-decoration: underline;" moz-do-not-send="true"><martinfox656@gmail.com></a><br>
<b>Date:<span
class="Apple-converted-space"> </span></b>Monday, March 10, 2025 at
10:10<br>
<b>To:<span
class="Apple-converted-space"> </span></b>Christopher Schnick<span
class="Apple-converted-space"> </span><a
href="mailto:crschnick@xpipe.io"
style="color: blue; text-decoration: underline;" moz-do-not-send="true"><crschnick@xpipe.io></a><br>
<b>Cc:<span
class="Apple-converted-space"> </span></b>OpenJFX<span
class="Apple-converted-space"> </span><a
href="mailto:openjfx-dev@openjdk.org"
style="color: blue; text-decoration: underline;" moz-do-not-send="true"><openjfx-dev@openjdk.org></a><br>
<b>Subject:<span
class="Apple-converted-space"> </span></b>Re: JVM crashes on macOS when
entering too
many nested
event loops</span><o:p></o:p></p>
</div>
<div>
<p
class="MsoNormal"
style="margin: 0in 0in 12pt; font-size: 10pt; font-family: Aptos, sans-serif;"><span
style="font-size: 11pt;">Hi Christopher,<br>
<br>
I was able to
reproduce this
crash. I wrote
a small
routine that
recursively
calls itself
in a runLater
block and then
enters a
nested event
loop. The
program
crashes when
creating loop
254. I’m not
sure where
that limit
comes from so
it’s possible
that consuming
some other
system
resource could
lower it. I
couldn’t see
any good way
to determine
how many loops
are active by
looking at the
crash report
since it
doesn’t show
the entire
call stack.<br>
I did a quick
trial on Linux
and was able
to create a
lot more loops
(over 600) but
then started
seeing erratic
behavior and
errors coming
from the Java
VM. The
behavior was
variable
unlike on the
Mac which
always crashes
when creating
loop 254.<br>
<br>
Martin<br>
<br>
> On Mar 7,
2025, at 6:24</span><span
style="font-size: 11pt; font-family: Arial, sans-serif;"> </span><span
style="font-size: 11pt;">AM, Christopher Schnick<span
class="Apple-converted-space"> </span><a
href="mailto:crschnick@xpipe.io"
style="color: blue; text-decoration: underline;" moz-do-not-send="true"><crschnick@xpipe.io></a><span
class="Apple-converted-space"> </span>wrote:<br>
><span
class="Apple-converted-space"> </span><br>
> Hello,<br>
><span
class="Apple-converted-space"> </span><br>
> I have
attached a JVM
fatal error
log that
seemingly was
caused by our
JavaFX
application
entering too
many nested
event loops,
which macOS
apparently
doesn't like.<br>
><span
class="Apple-converted-space"> </span><br>
> As far as
I know, there
is no upper
limit defined
on how often
an event loop
can be nested,
so I think
this is a bug
that can occur
in rare
situations.<br>
><span
class="Apple-converted-space"> </span><br>
> Best<br>
>
Christopher
Schnick<hs_err_pid.txt></span></p>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
<br>
</blockquote>
</div>
</div>
</blockquote>
</div>
<br>
</blockquote>
</body>
</html>