Deadlock in BitmapEncoder
I got a CPU running at 100% for about 2hours. A tip from JStack showed this process not ending, which might be the cause: (it was frozen in the same place during all this period)
"getGraficoGrupos-U_pedro-E_Açaí-90" #43 daemon prio=5 os_prio=0 tid=0x00007f71fc00b000 nid=0x12d1 runnable [0x00007f71f11f9000]
java.lang.Thread.State: RUNNABLE
at sun.font.SunLayoutEngine.nativeLayout(Native Method)
at sun.font.SunLayoutEngine.layout(SunLayoutEngine.java:187)
at sun.font.GlyphLayout$EngineRecord.layout(GlyphLayout.java:685)
at sun.font.GlyphLayout.layout(GlyphLayout.java:466)
at sun.font.ExtendedTextSourceLabel.createGV(ExtendedTextSourceLabel.java:329)
at sun.font.ExtendedTextSourceLabel.getGV(ExtendedTextSourceLabel.java:315)
at sun.font.ExtendedTextSourceLabel.createLogicalBounds(ExtendedTextSourceLabel.java:225)
at sun.font.ExtendedTextSourceLabel.getAdvance(ExtendedTextSourceLabel.java:134)
at java.awt.font.TextLine.init(TextLine.java:281)
at java.awt.font.TextLine.<init>(TextLine.java:129)
at java.awt.font.TextLine.fastCreateTextLine(TextLine.java:983)
at java.awt.font.TextLayout.fastInit(TextLayout.java:612)
at java.awt.font.TextLayout.<init>(TextLayout.java:393)
at org.knowm.xchart.internal.chartpart.AxisTickCalculator_.willLabelsFitInTickSpaceHint(AxisTickCalculator_.java:144)
at org.knowm.xchart.internal.chartpart.AxisTickCalculator_.calculateForEquallySpacedAxisValues(AxisTickCalculator_.java:407)
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.getAxisTickCalculator(Axis.java:572)
at org.knowm.xchart.internal.chartpart.Axis.getYAxisWidthHint(Axis.java:349)
at org.knowm.xchart.internal.chartpart.Axis.preparePaint(Axis.java:159)
at org.knowm.xchart.internal.chartpart.AxisPair.paint(AxisPair.java:124)
at org.knowm.xchart.CategoryChart.paint(CategoryChart.java:308)
at org.knowm.xchart.BitmapEncoder.getBufferedImage(BitmapEncoder.java:281)
at org.knowm.xchart.BitmapEncoder.getBitmapBytes(BitmapEncoder.java:264)
at contahub.cmds.ChartCmd.getImgGraficoGrupos(ChartCmd.java:1468)
my code in line 1468 is nothing strange:
CategoryChart chart =
new CategoryChartBuilder()
... BUILD THE CHART
byte[] bytes = BitmapEncoder.getBitmapBytes(chart, BitmapFormat.PNG);
I could not repeat the error.
Any Clue?
I have hit this same issue. The deadlock originates at line 399 of AxisTickCalculator_.java in the calculateForEquallySpacedAxisValues method.
At line 393, span is calculated; however, if it is calculated as 0.0, the line below will calculate gridStep as NaN, which in turns results in gridStepInChartSpace being 0.
The call to willLabelsFitInTickSpaceHint() will always return false, and all subsequent calculations of span will be 0.0 and you end up in an infinite loop.
Please find below a minimal example to reproduce this issue:
import org.knowm.xchart.BitmapEncoder;
import org.knowm.xchart.XYChartBuilder;
import java.io.IOException;
import java.util.List;
public class XChartDeadlock {
public static void main(String[] args) throws IOException {
var chart = new XYChartBuilder()
.width(720)
.height(480)
.title("Deadlock Example")
.xAxisTitle("Count")
.yAxisTitle("Value")
.build();
// If the decimal places in the pattern is fewer than the largest data value, the deadlock occurs.
chart.getStyler().setDecimalPattern("#0.00");
var xValues = List.of(1, 2, 3, 4, 5, 6, 7, 8);
// The only value here is 0.001 which is one decimal place below the pattern.
var yValues = List.of(0.0, 0.0, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0);
chart.addSeries("main", xValues, yValues);
BitmapEncoder.getBitmapBytes(chart, BitmapEncoder.BitmapFormat.PNG);
}
}
The issue occurs when using setDecimalPattern. If your data values contains only one unique value greater than 0, and the number of decimal places of that value is more than you've specified in the pattern, the deadlock occurs.
To fix this example, you can either change the pattern to 3 decimal places or change one of the 0.0 xValues to another value other than 0.001.
I hope I've explained that OK.
Thanks for the example code. I'll try to fix it now...
Fix pushed, please test.
Hi @timmolter,
Yes, all is working correctly now. Thank you for fixing this.