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

BasicSliderUI throws NullPointerExc when JSlider maximum is Integer.MAX_VALUE

XMLWordPrintable

    • b02
    • x86
    • linux

        FULL PRODUCT VERSION :
        Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
        Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)

        ADDITIONAL OS VERSION INFORMATION :
        Linux artemis 2.6.24-21-generic #1 SMP Mon Aug 25 17:32:09 UTC 2008 i686 GNU/Linux (Kubuntu Hardy)
        Windows XP SP 3


        A DESCRIPTION OF THE PROBLEM :
        We have existing GUI code that uses a JSlider. It uses values between 0 and Integer.MAX_VALUE. It works fine on machines that run Java 5 (1.5.0_16), but it throws a NullPointerException (see below) when using Java 6.

        The reason is that BasicSliderUI was changed in Java 6. getHighestValueLabel() now calls the new method getLowestValue(), which is buggy. Let's take a look:

            protected Integer getLowestValue() {
                Dictionary dictionary = slider.getLabelTable();
                if (dictionary != null) {
                    Enumeration keys = dictionary.keys();
                    int min = slider.getMaximum() + 1;
                    while (keys.hasMoreElements()) {
                        min = Math.min(min, ((Integer)keys.nextElement()).intValue());
                    }
                    if (min == slider.getMaximum() + 1) {
                        return null;
                    }
                    return min;
                }
                return null;
            }

        If one of the keys is Integer.MAX_VALUE, then min is initialized with Integer.MAX_VALUE + 1 = Integer.MIN_VALUE (integer overflow).
        The loop doesn't change anything because Math.min(Integer.MIN_VALUE, x) always returns Integer.MIN_VALUE.
        So min == slider.getMaximum() + 1, and this method returns null.

        I have rewritten this method for my workaround. When using Java 6, my method will override the buggy method. When using Java 5, my workaround won't have any effects (which is good).

        Please review my code and consider to include it in BasicSlideUI.java.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Compile and run the attached source code.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Slider with labels at zero and maximum.

        ERROR MESSAGES/STACK TRACES THAT OCCUR :
        Exception in thread "main" java.lang.NullPointerException
                at javax.swing.plaf.basic.BasicSliderUI.calculateTrackBuffer(BasicSliderUI.java:585)
                at javax.swing.plaf.basic.BasicSliderUI.calculateGeometry(BasicSliderUI.java:510)
                at javax.swing.plaf.basic.BasicSliderUI$Handler.propertyChange(BasicSliderUI.java:1448)
                at javax.swing.plaf.basic.BasicSliderUI$PropertyChangeHandler.propertyChange(BasicSliderUI.java:725)
                at javax.swing.plaf.metal.MetalSliderUI$MetalPropertyListener.propertyChange(MetalSliderUI.java:129)
                at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:339)
                at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:276)
                at java.awt.Component.firePropertyChange(Component.java:7868)
                at javax.swing.JSlider.setLabelTable(JSlider.java:794)
                at SliderTest.main(SliderTest.java:41)


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.util.Dictionary;
        import java.util.Enumeration;
        import java.util.Hashtable;

        import javax.swing.JFrame;
        import javax.swing.JLabel;
        import javax.swing.JSlider;
        import javax.swing.plaf.basic.BasicSliderUI;

        public class SliderTest {
            public static void main(String[] args) {
                JFrame frame = new JFrame("Test");

                JSlider slider = new JSlider(0, Integer.MAX_VALUE);

                slider.setPaintLabels(true);

                Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
                labelTable.put(0, new JLabel("Zero"));
                labelTable.put(Integer.MAX_VALUE, new JLabel("Maximum"));

                slider.setLabelTable(labelTable);
                frame.add(slider);

                frame.pack();
                frame.setVisible(true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        }
        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        import java.util.Dictionary;
        import java.util.Enumeration;
        import java.util.Hashtable;

        import javax.swing.JFrame;
        import javax.swing.JLabel;
        import javax.swing.JSlider;
        import javax.swing.plaf.basic.BasicSliderUI;

        public class SliderTest {
            public static void main(String[] args) {
                JFrame frame = new JFrame("Test");

                JSlider slider = new JSlider(0, Integer.MAX_VALUE);

        // ######### START WORKAROUND ################
        // slider.setUI(new BasicSliderUI(slider) {
        // protected Integer getLowestValue() {
        // Dictionary dictionary = slider.getLabelTable();
        // if (dictionary != null) {
        // Enumeration keys = dictionary.keys();
        // if (!keys.hasMoreElements()) {
        // return null;
        // }
        //
        // int min = Integer.MAX_VALUE;
        // while (keys.hasMoreElements()) {
        // min = Math.min(min, ((Integer) keys.nextElement())
        // .intValue());
        // }
        // return min;
        // }
        // return null;
        // }
        // });
        // ######### END WORKAROUND ################

                slider.setPaintLabels(true);

                Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
                labelTable.put(0, new JLabel("Zero"));
                labelTable.put(Integer.MAX_VALUE, new JLabel("Maximum"));

                slider.setLabelTable(labelTable);
                frame.add(slider);

                frame.pack();
                frame.setVisible(true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        }

        Release Regression From : 6
        The above release value was the last known release where this
        bug was not reproducible. Since then there has been a regression.

              rupashka Pavel Porvatov (Inactive)
              igor Igor Nekrestyanov (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: