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

Swing LayoutComparator may lead to IllegalArgumentException

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 7u21
    • client-libs

      FULL PRODUCT VERSION :
      java version "1.7.0_21"
      Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
      Java HotSpot(TM) Client VM (build 23.21-b01, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      This bug is a duplicate of JDK-6923200, which have been closed with "Cannot Reproduce". I have attached a small program which reproduces the bug.

      The comparator LayoutComparator breaks transitivity, which makes the EDT throw IllegalArgumentException when doing layout.

      When LayoutComparator compares two components with only a small difference in y, it compares the x coordinate, but if the y corrdinates differ by 10 or more it compares the y coordinate. Example of transitivity problem:

      C1: x=10 y=0
      C2: x=5 y =5
      C3: x=0 y=10

      C1 > C2 : Difference in y is less than 10, so x is compared (C1.x > C2.x)
      C2 > C3 : Difference in y is less than 10, so x is compared (C2.x > C3.x)
      C3 > C1: Differnce in y is not less than 10, so y is compared (C3.y > C1.y)

      With Java 7 the new TimSort sometimes detects such inconsistencies and throws an IllegalArgumentException.

      Either the comparator should be transitive or another sorting algorithm is needed when using the comparator.


      REGRESSION. Last worked in version 6u43

      REGRESSION : Additional Information
      java version "1.6.0_38"
      Java(TM) SE Runtime Environment (build 1.6.0_38-b05)
      Java HotSpot(TM) 64-Bit Server VM (build 20.13-b02, mixed mode)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached Java program.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      No exception on EDT
      ACTUAL -
      IllegalArgumentException on EDT

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Comparison method violates its general contract!
      at java.util.TimSort.mergeHi(TimSort.java:868)
      at java.util.TimSort.mergeAt(TimSort.java:485)
      at java.util.TimSort.mergeForceCollapse(TimSort.java:426)
      at java.util.TimSort.sort(TimSort.java:223)
      at java.util.TimSort.sort(TimSort.java:173)
      at java.util.Arrays.sort(Arrays.java:659)
      at java.util.Collections.sort(Collections.java:217)
      at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(SortingFocusTraversalPolicy.java:136)
      at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(SortingFocusTraversalPolicy.java:110)
      at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(SortingFocusTraversalPolicy.java:435)
      at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(LayoutFocusTraversalPolicy.java:166)
      at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(SortingFocusTraversalPolicy.java:515)
      at java.awt.FocusTraversalPolicy.getInitialComponent(FocusTraversalPolicy.java:169)
      at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:380)
      at java.awt.Component.dispatchEventImpl(Component.java:4731)
      at java.awt.Container.dispatchEventImpl(Container.java:2287)
      at java.awt.Window.dispatchEventImpl(Window.java:2719)
      at java.awt.Component.dispatchEvent(Component.java:4687)
      at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:729)
      at java.awt.EventQueue.access$200(EventQueue.java:103)
      at java.awt.EventQueue$3.run(EventQueue.java:688)
      at java.awt.EventQueue$3.run(EventQueue.java:686)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
      at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
      at java.awt.EventQueue$4.run(EventQueue.java:702)
      at java.awt.EventQueue$4.run(EventQueue.java:700)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
      at java.awt.EventQueue.dispatchEvent(EventQueue.java:699)
      at java.awt.SequencedEvent.dispatch(SequencedEvent.java:128)
      at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
      at java.awt.EventQueue.access$200(EventQueue.java:103)
      at java.awt.EventQueue$3.run(EventQueue.java:688)
      at java.awt.EventQueue$3.run(EventQueue.java:686)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
      at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
      at java.awt.EventQueue$4.run(EventQueue.java:702)
      at java.awt.EventQueue$4.run(EventQueue.java:700)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
      at java.awt.EventQueue.dispatchEvent(EventQueue.java:699)
      at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
      at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
      at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

      REPRODUCIBILITY :
      This bug can be reproduced always.

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

      import javax.swing.*;

      public class TestLayoutBug extends JFrame
      {
        private static TestLayoutBug dia;
        
        private static int[] Xs = new int[] {71, 23, 62, 4, 79, 39, 34, 9, 84, 58, 30, 34, 38, 15, 69, 10, 44, 95, 70, 54,
          44, 62, 77, 64, 70, 83, 31, 48, 96, 54, 40, 3, 60, 58, 3, 20, 94, 54, 26, 19, 48, 47, 12, 70, 86, 43, 71, 97, 19,
          69, 90, 22, 43, 76, 10, 60, 29, 49, 9, 9, 15, 73, 85, 80, 81, 35, 87, 43, 17, 57, 38, 44, 29, 86, 96, 15, 57, 26,
          27, 78, 26, 87, 43, 6, 4, 16, 57, 99, 32, 86, 96, 5, 50, 69, 12, 4, 36, 84, 71, 60, 22, 46, 11, 44, 87, 3, 23, 14,
          43, 25, 32, 44, 11, 18, 77, 2, 51, 87, 88, 53, 69, 37, 14, 10, 25, 73, 39, 33, 91, 51, 96, 9, 74, 66, 70, 42, 72,
          7, 82, 40, 91, 33, 83, 54, 33, 50, 83, 1, 81, 32, 66, 11, 75, 56, 53, 45, 1, 69, 46, 31, 79, 58, 12, 20, 92, 49,
          50, 90, 33, 8, 43, 93, 72, 78, 9, 56, 84, 60, 30, 39, 33, 88, 84, 56, 49, 47, 4, 90, 57, 6, 23, 96, 37, 88, 22, 79,
          35, 80, 45, 55};

        public TestLayoutBug()
        {
          JPanel panel = new JPanel(new GridBagLayout());
          GridBagConstraints gbc = new GridBagConstraints();
          for (int i=0; i < Xs.length; i++) {
            gbc.gridx = Xs[i];
            gbc.gridy = 100-gbc.gridx;
            panel.add(new MyComponent(), gbc);
          }
          getRootPane().getContentPane().add(panel);
          pack();
          setDefaultCloseOperation(EXIT_ON_CLOSE);
        }
        
        public static void main(String[] args) throws Exception
        {
          //System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
          SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run()
            {
              dia = new TestLayoutBug();
              dia.setVisible(true);
            }
          });
        }

        public static class MyComponent extends JPanel
        {
          private final static Dimension SIZE = new Dimension(1,1);
          
          public MyComponent()
          {
            setBackground(Color.BLACK);
            setOpaque(true);
          }

          @Override
          public Dimension getPreferredSize()
          {
            return SIZE;
          }
        }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Disable new sorting algorithm:

      System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

            alexsch Alexandr Scherbatiy
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: