Uploaded image for project: 'Drools'
  1. Drools
  2. DROOLS-2346

ProtobufOutputMarshaller.orderFacts causes a "Comparison method violates its general contract" error

    Details

    • Type: Bug
    • Status: Resolved (View Workflow)
    • Priority: Major
    • Resolution: Done
    • Affects Version/s: 7.6.0.Final
    • Fix Version/s: None
    • Component/s: core engine
    • Labels:
      None
    • Sprint:
      2018 Week 07-08
    • Docs QE Status:
      NEW
    • QE Status:
      NEW

      Description

      When marshalling kieSession in production (long running kieSession with a lot of fact insertion), we encountered the following error :

      java.lang.IllegalArgumentException: Comparison method violates its general contract!
      	at java.util.TimSort.mergeLo(TimSort.java:777)
      	at java.util.TimSort.mergeAt(TimSort.java:514)
      	at java.util.TimSort.mergeCollapse(TimSort.java:439)
      	at java.util.TimSort.sort(TimSort.java:245)
      	at java.util.Arrays.sort(Arrays.java:1438)
      	at org.drools.core.marshalling.impl.ProtobufOutputMarshaller.orderFacts(ProtobufOutputMarshaller.java:776)
      	at org.drools.core.marshalling.impl.ProtobufOutputMarshaller.writeFactHandles(ProtobufOutputMarshaller.java:707)
      	at org.drools.core.marshalling.impl.ProtobufOutputMarshaller.serializeSession(ProtobufOutputMarshaller.java:176)
      	at org.drools.core.marshalling.impl.ProtobufOutputMarshaller.writeSession(ProtobufOutputMarshaller.java:120)
      	at org.drools.core.marshalling.impl.ProtobufMarshaller.marshall(ProtobufMarshaller.java:164)
      	at org.drools.core.marshalling.impl.ProtobufMarshaller.marshall(ProtobufMarshaller.java:148)
      

      Indeed, the orderFacts method in ProtobufoutputMarshaller uses a HandleSorter as comparator, which returns the result of o1.getId() - o2.getId() where o1 and o2 are InternalFactHandle.

      Since the id of InternalFactHandle is an int, this comparator can cause "Comparison method violates its general contract!" IllegalArgumentException because Integer.MAX_INT + 1 < 0.
      The comparator should return the result of Integer.compare(o1.getId(), o2.getId())

      The root cause is that InternalFactHandle.getId() is an int and should be a long for long running kieSession.
      This id is generated by the FactHandleFactory (in AbstractFactHandleFactory) and is an AtomicInteger incremented at each fact creation.
      With long running kieSession a lot of fact handles can be created (inserted in memory or with "from") so this id can overflow Integer.MAX_INT and become negative, causing this issue when ordering.

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  mfusco Mario Fusco
                  Reporter:
                  mputz Martin Weiler
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  2 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: