UI Freeze When Chart Window is Too Narrow (willLabelsFitInTickSpaceHint()) · Issue #886 · knowm/XChart · GitHub
More Web Proxy on the site http://driver.im/
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi!
We've encountered an issue where XChart can completely freeze the UI thread when a plot window is too narrow. It looks like willLabelsFitInTickSpaceHint() in AxisTickCalculator_ gets stuck, causing the AWT Event Dispatch Thread (EDT) to never return.
We're not entirely sure what's happening, but when the plot window starts too small, the UI becomes unresponsive and never recovers. This is a problem for us since we use two threads, one fetching data while the other spawns the chart that's too narrow at the start.
The issue is present on both Java 8 and 17, with the latest version of XChart 3.8.8
We've taken a thread dump to see where the UI thread is stuck:
"AWT-EventQueue-0" #34 prio=6 os_prio=0 cpu=15281.25ms elapsed=265.88s tid=0x0000016bcc920e20 nid=0x79c4 runnable [0x000000371f7fc000]
java.lang.Thread.State: RUNNABLE
at java.awt.geom.Path2D$Float.append(java.desktop@17.0.10/Path2D.java:786)
at java.awt.geom.Path2D.append(java.desktop@17.0.10/Path2D.java:1975)
at java.awt.font.TextLine.getOutline(java.desktop@17.0.10/TextLine.java:874)
at java.awt.font.TextLayout.getOutline(java.desktop@17.0.10/TextLayout.java:2663)
at org.knowm.xchart.internal.chartpart.AxisTickCalculator_.willLabelsFitInTickSpaceHint(AxisTickCalculator_.java:140)
at org.knowm.xchart.internal.chartpart.AxisTickCalculator_.calculateForEquallySpacedAxisValues(AxisTickCalculator_.java:408)
at org.knowm.xchart.internal.chartpart.AxisTickCalculator_.calculate(AxisTickCalculator_.java:205)
at org.knowm.xchart.internal.chartpart.AxisTickCalculator_Number.<init>(AxisTickCalculator_Number.java:47)
at org.knowm.xchart.internal.chartpart.Axis.getAxisTickCalculatorForX(Axis.java:547)
at org.knowm.xchart.internal.chartpart.Axis.getAxisTickCalculator(Axis.java:390)
at org.knowm.xchart.internal.chartpart.Axis.getXAxisHeightHint(Axis.java:293)
at org.knowm.xchart.internal.chartpart.Axis.preparePaint(Axis.java:161)
at org.knowm.xchart.internal.chartpart.AxisPair.paint(AxisPair.java:120)
at org.knowm.xchart.XYChart.paint(XYChart.java:416)
at org.knowm.xchart.XChartPanel.paintComponent(XChartPanel.java:166)
at javax.swing.JComponent.paint(java.desktop@17.0.10/JComponent.java:1119)
at javax.swing.JComponent.paintChildren(java.desktop@17.0.10/JComponent.java:952)
- locked <0x000000040207c240> (a java.awt.Component$AWTTreeLock)
at javax.swing.JComponent.paint(java.desktop@17.0.10/JComponent.java:1128)
at javax.swing.JComponent.paintChildren(java.desktop@17.0.10/JComponent.java:952)
- locked <0x000000040207c240> (a java.awt.Component$AWTTreeLock)
at javax.swing.JComponent.paint(java.desktop@17.0.10/JComponent.java:1128)
at javax.swing.JLayeredPane.paint(java.desktop@17.0.10/JLayeredPane.java:586)
at javax.swing.JComponent.paintChildren(java.desktop@17.0.10/JComponent.java:952)
- locked <0x000000040207c240> (a java.awt.Component$AWTTreeLock)
at javax.swing.JComponent.paintToOffscreen(java.desktop@17.0.10/JComponent.java:5318)
at javax.swing.RepaintManager$PaintManager.paintDoubleBufferedFPScales(java.desktop@17.0.10/RepaintManager.java:1721)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(java.desktop@17.0.10/RepaintManager.java:1630)
at javax.swing.RepaintManager$PaintManager.paint(java.desktop@17.0.10/RepaintManager.java:1570)
at javax.swing.RepaintManager.paint(java.desktop@17.0.10/RepaintManager.java:1337)
at javax.swing.JComponent.paint(java.desktop@17.0.10/JComponent.java:1105)
at java.awt.GraphicsCallback$PaintCallback.run(java.desktop@17.0.10/GraphicsCallback.java:39)
at sun.awt.SunGraphicsCallback.runOneComponent(java.desktop@17.0.10/SunGraphicsCallback.java:75)
at sun.awt.SunGraphicsCallback.runComponents(java.desktop@17.0.10/SunGraphicsCallback.java:112)
at java.awt.Container.paint(java.desktop@17.0.10/Container.java:2005)
at java.awt.Window.paint(java.desktop@17.0.10/Window.java:3959)
at javax.swing.RepaintManager$4.run(java.desktop@17.0.10/RepaintManager.java:890)
at javax.swing.RepaintManager$4.run(java.desktop@17.0.10/RepaintManager.java:862)
at java.security.AccessController.executePrivileged(java.base@17.0.10/AccessController.java:776)
at java.security.AccessController.doPrivileged(java.base@17.0.10/AccessController.java:399)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(java.base@17.0.10/ProtectionDomain.java:86)
at javax.swing.RepaintManager.paintDirtyRegions(java.desktop@17.0.10/RepaintManager.java:862)
at javax.swing.RepaintManager.paintDirtyRegions(java.desktop@17.0.10/RepaintManager.java:835)
at javax.swing.RepaintManager.prePaintDirtyRegions(java.desktop@17.0.10/RepaintManager.java:784)
at javax.swing.RepaintManager$ProcessingRunnable.run(java.desktop@17.0.10/RepaintManager.java:1898)
at java.awt.event.InvocationEvent.dispatch(java.desktop@17.0.10/InvocationEvent.java:318)
at java.awt.EventQueue.dispatchEventImpl(java.desktop@17.0.10/EventQueue.java:773)
at java.awt.EventQueue$4.run(java.desktop@17.0.10/EventQueue.java:720)
at java.awt.EventQueue$4.run(java.desktop@17.0.10/EventQueue.java:714)
at java.security.AccessController.executePrivileged(java.base@17.0.10/AccessController.java:776)
at java.security.AccessController.doPrivileged(java.base@17.0.10/AccessController.java:399)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(java.base@17.0.10/ProtectionDomain.java:86)
at java.awt.EventQueue.dispatchEvent(java.desktop@17.0.10/EventQueue.java:742)
at java.awt.EventDispatchThread.pumpOneEventForFilters(java.desktop@17.0.10/EventDispatchThread.java:203)
at java.awt.EventDispatchThread.pumpEventsForFilter(java.desktop@17.0.10/EventDispatchThread.java:124)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(java.desktop@17.0.10/EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(java.desktop@17.0.10/EventDispatchThread.java:109)
at java.awt.EventDispatchThread.pumpEvents(java.desktop@17.0.10/EventDispatchThread.java:101)
at java.awt.EventDispatchThread.run(java.desktop@17.0.10/EventDispatchThread.java:90)
Locked ownable synchronizers:
- None
To Reproduce
This happens even in the standard XChart example when the window is too small.
Describe the bug
Hi!
We've encountered an issue where
XChart
can completely freeze the UI thread when a plot window is too narrow. It looks likewillLabelsFitInTickSpaceHint()
inAxisTickCalculator_
gets stuck, causing the AWT Event Dispatch Thread (EDT) to never return.We're not entirely sure what's happening, but when the plot window starts too small, the UI becomes unresponsive and never recovers. This is a problem for us since we use two threads, one fetching data while the other spawns the chart that's too narrow at the start.
The issue is present on both Java 8 and 17, with the latest version of XChart
3.8.8
We've taken a thread dump to see where the UI thread is stuck:
To Reproduce
This happens even in the standard XChart example when the window is too small.
Screenshots
Here's a very rough video of the issue, note that it doesn't always take this long to occur.
Recording.2025-02-04.103113.mp4
This leads to high memory usage over time. Here’s Java 8 vs. 17:
Expected behavior
The UI thread should not block indefinitely. If the tick labels can't fit either:
The text was updated successfully, but these errors were encountered: