Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8136535

JavaFX NumberAxis AutoRange Infinite Loop

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 8u40
    • Fix Version/s: 9
    • Component/s: javafx
    • Labels:
    • Subcomponent:
    • Introduced In Version:
    • CPU:
      x86
    • OS:
      windows_8

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.8.0_60"
        Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
        Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [Version 10.0.10240]

        A DESCRIPTION OF THE PROBLEM :
        The NumberAxis.autoRange method may enter an infinite loop if consecutive double values are added to a chart that are very close together. This is noticeable because the JavaFX thread will hang due to the infinite loop.

        The chart axis must have auto ranging enabled and NumberAxis.setForceZeroInRange(false).

        See attached minimal, complete, and verifiable example to repro.

        See http://stackoverflow.com/questions/32513409/javafx-numberaxis-autorange-infinite-loop

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        1. Create LineChart
        2. Create Y-Axis NumberAxis with auto range enable and setForceZeroInRange(false)
        3. Add -20.98295609742171 to Y-Axis
        4. Add -20.982956097421706 to Y-Axis

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The JavaFX thread should not hang and the chart should continue to update.
        ACTUAL -
        The JavaFX thread hangs and the chart stops updating

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.util.*;

        import javafx.application.*;
        import javafx.concurrent.*;
        import javafx.scene.*;
        import javafx.scene.chart.*;
        import javafx.stage.*;
        import javafx.util.*;

        public class SmallTickUnitTest extends Application {

          @Override
          public void start(Stage stage) {
            final NumberAxis xAxis = new NumberAxis();
            final NumberAxis yAxis = new NumberAxis();
            final LineChart<Number, Number> lineChart = new LineChart<>(xAxis, yAxis);

            xAxis.setLabel("Time");
            yAxis.setLabel("Data");
            lineChart.setTitle("Measured Data");

            XYChart.Series<Number, Number> series1 = new XYChart.Series<>();
            series1.setName("Wind Speed");
            lineChart.getData().addAll(series1);
            
            // If this is set to true then the bug will not occur
            yAxis.setForceZeroInRange(false);

            // Use two values that are extremely close together
            List<Double> values = Arrays.asList(-20.98295609742171, -20.982956097421706);
            final Iterator<Double> itr = values.iterator();
            
            ScheduledService<XYChart.Data<Number, Number>> svc =
               new ScheduledService<XYChart.Data<Number, Number>>() {

              int time = 0;

              @Override
              protected Task<XYChart.Data<Number, Number>> createTask() {
                return new Task<XYChart.Data<Number, Number>>() {
                  @Override
                  protected XYChart.Data<Number, Number> call() {
                    time++;
                    return new XYChart.Data<>(time, itr.hasNext() ? itr.next() : 0);
                  }
                };
              }
            };
            
            svc.setPeriod(Duration.seconds(2));
            svc.setRestartOnFailure(true);
            svc.setOnSucceeded((WorkerStateEvent e) -> {
              XYChart.Data<Number, Number> value = svc.getLastValue();
              if (value != null) {
                series1.getData().add(value);
              }
            });

            Scene scene = new Scene(lineChart, 800, 600);
            stage.setTitle("Line Chart Sample");
            stage.setScene(scene);
            stage.show();
            svc.start();
          }

          public static void main(String[] args) {
            launch(args);
          }
        }
        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Sanitize floating point chart input data such that values cannot be close to each other.

          Attachments

            Issue Links

              Activity

                People

                Assignee:
                vadim Vadim Pakhnushev
                Reporter:
                webbuggrp Webbug Group
                Votes:
                0 Vote for this issue
                Watchers:
                6 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved: