Forum Stats

  • 3,734,876 Users
  • 2,247,063 Discussions
  • 7,857,535 Comments

Discussions

Illegal Argument exception within Swing

ptoye
ptoye Member Posts: 72
edited Oct 28, 2012 8:53AM in Java Programming
I've written a Swing-based program. When I start it there's an Illegal Argument exception with the message "Comparison method violates its general contract".

But the stack doesn't have any of my code in it - it's entirely on the AWT event queue (see copy of stack below). And there are no comparators in my program at all.

The program appears to run OK, but it's more than a bit disconcerting. Anyone here got any ideas what's going wrong inside Swing?

Thanks in advance,

Peter

Stack output is:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:747)
at java.util.TimSort.mergeAt(TimSort.java:483)
at java.util.TimSort.mergeCollapse(TimSort.java:410)
at java.util.TimSort.sort(TimSort.java:214)
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:723)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:682)
at java.awt.EventQueue$3.run(EventQueue.java:680)
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:696)
at java.awt.EventQueue$4.run(EventQueue.java:694)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:693)
at java.awt.SequencedEvent.dispatch(SequencedEvent.java:116)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:721)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:682)
at java.awt.EventQueue$3.run(EventQueue.java:680)
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:696)
at java.awt.EventQueue$4.run(EventQueue.java:694)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:693)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)

Best Answer

  • darrylburke
    darrylburke Member Posts: 18,007
    Accepted Answer
    ptoye wrote:
    Yes, but what's the syntax of the property string? I've tried "true", "TRUE", "Boolean.true", "Boolean.TRUE", "boolean.TRUE" and other combinations of upper- and lower-case. And the sun.security.action package isn't in the published Javadoc so it's not easy to find out just what it wants.
    The correct value woud be <tt><b>"true"</b></tt>, as recommended by doremifasollatido. But since the property is accessed from a static context, it would need to be set <b>before</b> the Arrays class is loaded.

    I guess you could try setting it from within a static initializer in your class that has the main(...) method and see if that takes. If it doesn't, you're left with the command line argument as the only option.

    db
«1

Answers

  • TPD-Opitz
    TPD-Opitz Member Posts: 2,465 Silver Trophy
    Find all your Classes implementing <tt>Comparable</tt> interface.
    Do they fullfill the restriction given in
    http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html?

    This classes should not only implement <tt>compareTo(T other)</tt> but also <tt>equals</tt> (and therefore <tt>hashcode()</tt> too).

    bye
    TPD
  • Kayaman
    Kayaman Member Posts: 3,844 Silver Trophy
    ptoye wrote:
    But the stack doesn't have any of my code in it
    It may be sorting instances of your classes that have fudged the general contract.

    If you have any JComponent subclasses, check that their equals and hashcode methods are correctly implemented.
  • ptoye
    ptoye Member Posts: 72
    edited Oct 23, 2012 12:17PM
    Kayaman wrote:
    If you have any JComponent subclasses, check that their equals and hashcode methods are correctly implemented.
    I have only one such class, which extends JComponent. I've not overridden either equals or hashcode as there doesn't seem to be much point. Or is there a subtle reason why I should write my own?

    There's also a class which extends JFrame, of course, to give me a window.

    Edited by: ptoye on Oct 23, 2012 9:12 AM

    Edited by: ptoye on Oct 23, 2012 9:16 AM

    Edited by: ptoye on Oct 23, 2012 9:17 AM
  • ptoye
    ptoye Member Posts: 72
    edited Oct 23, 2012 12:14PM
    TPD Opitz-Consulting com wrote:
    Find all your Classes implementing <tt>Comparable</tt> interface.
    Do they fullfill the restriction given in
    http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html?

    This classes should not only implement <tt>compareTo(T other)</tt> but also <tt>equals</tt> (and therefore <tt>hashcode()</tt> too).

    bye
    TPD
    I don't have any classes which directly implement Comparable. Only an extension of JComponent - see my other comment for details.

    Edited by: ptoye on Oct 23, 2012 9:13 AM
  • DrClap
    DrClap Member Posts: 25,479
    Then to see if that class is somehow the problem, have it implement the method required by Comparable trivially:
    public int compareTo(Object other) {
      return super.compareTo(other);
    }
    This won't change the behaviour of your code, but it might make your class show up in the stack trace.
  • abillconsl
    abillconsl Member Posts: 2,556 Silver Badge
    "the stack doesn't have any of my code in it "

    What about this: java.util.TimSort.mergeLo(TimSort.java:747) ?
  • ptoye
    ptoye Member Posts: 72
    Thanks Dr. Clap.

    But JComponent (and its supers) don't implement CompareTo. Overriding the Equals and HashCode methods doesn't change anything.
  • ptoye
    ptoye Member Posts: 72
    edited Oct 23, 2012 2:04PM
    abillconsl wrote:

    What about this: java.util.TimSort.mergeLo(TimSort.java:747) ?
    Err.... That's part of the Java run-time. java.util is supplied by Java, not me!

    Edited by: ptoye on Oct 23, 2012 11:04 AM
  • abillconsl
    abillconsl Member Posts: 2,556 Silver Badge
    Yes that's very true. I saw TimSort and well ... what version of Java are you running? I never noticed TimSort before, I am running v1.6.31
  • DrClap
    DrClap Member Posts: 25,479
    ptoye wrote:
    But JComponent (and its supers) don't implement CompareTo. Overriding the Equals and HashCode methods doesn't change anything.
    No, you're correct, that's apparent to anybody who looks at the API. (Which I only just did now.) Then what is it which SortingFocusTraversalPolicy is sorting? Maybe it's time to have a look into the source code (src.zip in your JDK download). It's not impossible that the bug is in Oracle's code.
  • javax.swing.LayoutComparator seems to be the default comparator for the javax.swing.LayoutFocusTraversalPolicy, and LayoutComparator doesn't define equals. This seems to be a bug in Java 7---they didn't define equals in LayoutComparator, so sorting now fails.

    http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source says:
    Area: API: Utilities
    Synopsis: Updated sort behavior for Arrays and Collections may throw an IllegalArgumentException
    Description: The sorting algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort has been replaced. The new sort implementation may throw an
    IllegalArgumentException if it detects a Comparable that violates the Comparable contract. The previous implementation silently ignored such a situation.
    If the previous behavior is desired, you can use the new system property, java.util.Arrays.useLegacyMergeSort, to restore previous mergesort behavior.
    Nature of Incompatibility: behavioral
    RFE: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6804124
    Note the system property mentioned in that description that you can use to get the pre-Java7 behavior.

    Indeed, this bug has already been reported:
    http://webcache.googleusercontent.com/search?q=cache:QDf6QjnHLS8J:bugs.sun.com/bugdatabase/view_bug.do%3Fbug_id%3D7176968+&cd=12&hl=en&ct=clnk&gl=us
  • ptoye
    ptoye Member Posts: 72
    abillconsl wrote:
    what version of Java are you running? I never noticed TimSort before, I am running v1.6.31
    Version 7. Maybe I shouldn't have upgraded. Oracle seem to have put all sorts of bugs into 7.
  • ptoye
    ptoye Member Posts: 72
    edited Oct 24, 2012 5:14AM
    doremifasollatido wrote:
    javax.swing.LayoutComparator seems to be the default comparator for the javax.swing.LayoutFocusTraversalPolicy, and LayoutComparator doesn't define equals. This seems to be a bug in Java 7---they didn't define equals in LayoutComparator, so sorting now fails.

    Indeed, this bug has already been reported:
    http://webcache.googleusercontent.com/search?q=cache:QDf6QjnHLS8J:bugs.sun.com/bugdatabase/view_bug.do%3Fbug_id%3D7176968+&cd=12&hl=en&ct=clnk&gl=us
    Thanks. That bug (7176968) seems to have disappeared from the Oracle bug database. I begin to get the feeling that Oracle are removing adverse comments. I wonder why?

    [later] I tried setting the property. The article you reference doesn't tell me what to set it to. So I tried null (not allowed), "0" and "1" both of which don't change anything. All a bit dispiriting really.

    Edited by: ptoye on Oct 24, 2012 2:12 AM - results of test
  • ptoye
    ptoye Member Posts: 72
    DrClap wrote:

    No, you're correct, that's apparent to anybody who looks at the API. (Which I only just did now.) Then what is it which SortingFocusTraversalPolicy is sorting? Maybe it's time to have a look into the source code (src.zip in your JDK download). It's not impossible that the bug is in Oracle's code.
    This seems to be the current opinion.

    Oracle change something, don't test it and get surprised and defensive when people complain. The way of the world.
  • abillconsl
    abillconsl Member Posts: 2,556 Silver Badge
    ptoye wrote:
    Oracle change something, don't test it and get surprised and defensive when people complain. The way of the world.
    Yup, though in this case hopefully they'll at least fix it.
  • doremifasollatido
    doremifasollatido Member Posts: 1,935
    edited Oct 24, 2012 10:23AM
    ptoye wrote:
    doremifasollatido wrote:
    javax.swing.LayoutComparator seems to be the default comparator for the javax.swing.LayoutFocusTraversalPolicy, and LayoutComparator doesn't define equals. This seems to be a bug in Java 7---they didn't define equals in LayoutComparator, so sorting now fails.

    Indeed, this bug has already been reported:
    http://webcache.googleusercontent.com/search?q=cache:QDf6QjnHLS8J:bugs.sun.com/bugdatabase/view_bug.do%3Fbug_id%3D7176968+&cd=12&hl=en&ct=clnk&gl=us
    Thanks. That bug (7176968) seems to have disappeared from the Oracle bug database. I begin to get the feeling that Oracle are removing adverse comments. I wonder why?

    [later] I tried setting the property. The article you reference doesn't tell me what to set it to. So I tried null (not allowed), "0" and "1" both of which don't change anything. All a bit dispiriting really.
    I'd guess that you should set the property to "true". Based on the name, I'd say it needs a boolean value. I know nothing about it--I use Java 6, and found the cited reference and bug from a Google search. Good luck!
  • ptoye
    ptoye Member Posts: 72
    edited Oct 25, 2012 5:53AM
    doremifasollatido wrote:
    I'd guess that you should set the property to "true". Based on the name, I'd say it needs a boolean value. I know nothing about it--I use Java 6, and found the cited reference and bug from a Google search. Good luck!
    Tried "true". Still no change! Ditto with the empty string. Not impressed.

    Edited by: ptoye on Oct 25, 2012 2:53 AM Added quote.
  • abillconsl
    abillconsl Member Posts: 2,556 Silver Badge
    Why don't you just go back to v6x until this gets fixed? That's what I would do anyway. Less aggravation is better.
  • darrylburke
    darrylburke Member Posts: 18,007
    doremifasollatido wrote:
    I'd guess that you should set the property to "true". Based on the name, I'd say it needs a boolean value. I know nothing about it--I use Java 6, and found the cited reference and bug from a Google search. Good luck!
    From looking at the Java 7 source code of java.util.Arrays, I'd guess that you need to set <tt>"java.util.Arrays.useLegacyMergeSort"</tt> to <tt>Boolean.TRUE</tt>. There's a nested class
        static final class LegacyMergeSort {
            private static final boolean userRequested =
                java.security.AccessController.doPrivileged(
                    new sun.security.action.GetBooleanAction(
                        "java.util.Arrays.useLegacyMergeSort")).booleanValue();
        }
    and the sort(...) methods use this:
        public static void sort(Object[] a) {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a);
            else
                ComparableTimSort.sort(a);
        }
    db
    darrylburke
  • doremifasollatido
    doremifasollatido Member Posts: 1,935
    edited Oct 25, 2012 5:20PM
    Darryl Burke wrote:
    doremifasollatido wrote:
    I'd guess that you should set the property to "true". Based on the name, I'd say it needs a boolean value. I know nothing about it--I use Java 6, and found the cited reference and bug from a Google search. Good luck!
    From looking at the Java 7 source code of java.util.Arrays, I'd guess that you need to set <tt>"java.util.Arrays.useLegacyMergeSort"</tt> to <tt>Boolean.TRUE</tt>.
    But, you have to set properties to String values, so to get <tt>Boolean.TRUE</tt>, you would need to use the String <tt>"true"</tt>, as I suggested:
     System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); 
    Or, from the command line:
    <tt> -Djava.util.Arrays.useLegacyMergeSort=true </tt>
    doremifasollatido
  • ptoye
    ptoye Member Posts: 72
    abillconsl wrote:
    Why don't you just go back to v6x until this gets fixed?
    I'm thinking of it, but one of my other projects needs v7.

    And I get the feeling that trying to keep the versions separate would involve just as much aggravation. Especially installing v 6 after v 7.
  • ptoye
    ptoye Member Posts: 72
    edited Oct 26, 2012 2:18PM
    doremifasollatido wrote:

    But, you have to set properties to String values, so to get <tt>Boolean.TRUE</tt>, you would need to use the String <tt>"true"</tt>, as I suggested:
     System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); 
    Or, from the command line:
    <tt> -Djava.util.Arrays.useLegacyMergeSort=true </tt>
    As I said elsewhere the System.setProperty doesn't work. Neither does the suggestion of using "Boolean.TRUE" (and various combinations of upper- and lower-case). I've not looked for the

    But your command line works! Thanks very much.

    [later] After setting the property from the command line option, I printed out the value using System.getProperty - it's "true". But setting it to "true" using System.setProperty doesn't work.

    Is there some Boolean property type that can't be set from program, but can by command line?

    Edited by: ptoye on Oct 26, 2012 11:15 AM
  • ptoye
    ptoye Member Posts: 72
    Darryl Burke wrote:
    From looking at the Java 7 source code of java.util.Arrays, I'd guess that you need to set <tt>"java.util.Arrays.useLegacyMergeSort"</tt> to <tt>Boolean.TRUE</tt>. There's a nested class
        static final class LegacyMergeSort {
    private static final boolean userRequested =
    java.security.AccessController.doPrivileged(
    new sun.security.action.GetBooleanAction(
    "java.util.Arrays.useLegacyMergeSort")).booleanValue();
    }
    and the sort(...) methods use this:
        public static void sort(Object[] a) {
    if (LegacyMergeSort.userRequested)
    legacyMergeSort(a);
    else
    ComparableTimSort.sort(a);
    }
    db
    Yes, but what's the syntax of the property string? I've tried "true", "TRUE", "Boolean.true", "Boolean.TRUE", "boolean.TRUE" and other combinations of upper- and lower-case. And the sun.security.action package isn't in the published Javadoc so it's not easy to find out just what it wants.
  • darrylburke
    darrylburke Member Posts: 18,007
    doremifasollatido wrote:
    But, you have to set properties to String values, so to get <tt>Boolean.TRUE</tt>, you would need to use the String <tt>"true"</tt>, as I suggested:
    Ah, right. Sorry about that.

    db
  • darrylburke
    darrylburke Member Posts: 18,007
    Accepted Answer
    ptoye wrote:
    Yes, but what's the syntax of the property string? I've tried "true", "TRUE", "Boolean.true", "Boolean.TRUE", "boolean.TRUE" and other combinations of upper- and lower-case. And the sun.security.action package isn't in the published Javadoc so it's not easy to find out just what it wants.
    The correct value woud be <tt><b>"true"</b></tt>, as recommended by doremifasollatido. But since the property is accessed from a static context, it would need to be set <b>before</b> the Arrays class is loaded.

    I guess you could try setting it from within a static initializer in your class that has the main(...) method and see if that takes. If it doesn't, you're left with the command line argument as the only option.

    db
This discussion has been closed.