United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6794836 BasicSliderUI throws NullPointerExc when JSlider maximum is Integer.MAX_VALUE
JDK-6794836 : BasicSliderUI throws NullPointerExc when JSlider maximum is Integer.MAX_VALUE

Details
Type:
Bug
Submit Date:
2009-01-16
Status:
Resolved
Updated Date:
2011-01-19
Project Name:
JDK
Resolved Date:
2009-02-13
Component:
client-libs
OS:
linux
Sub-Component:
javax.swing
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:
6u14 (b02)

Related Reports
Backport:

Sub Tasks

Description
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.

                                    

Comments
EVALUATION

We should take into account such values as MAX_INT
                                     
2009-01-21



Hardware and Software, Engineered to Work Together