JBoss EAP 7 can fail to process a request due to "IllegalArgumentException: Comparison method violates its general contract!" when many filter-ref are defined in undertow subsystem
Environment
- Red Hat JBoss Enterprise Application Platform (EAP)
- 7.x
Issue
When many <filter-ref> settings are defined in the undertow subsystem, "500 Internal Server Error" is returned to the request due to "IllegalArgumentException: Comparison method violates its general contract!"
ERROR [io.undertow.request] (default I/O-12) UT005071: Undertow request failed HttpServerExchange{ GET /}: 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:441)
at java.util.TimSort.sort(TimSort.java:245)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1462)
at org.wildfly.extension.undertow.LocationService.configureHandlerChain(LocationService.java:93)
at org.wildfly.extension.undertow.Host.configureRootHandler(Host.java:174)
at org.wildfly.extension.undertow.Host.getOrCreateRootHandler(Host.java:263)
at org.wildfly.extension.undertow.Host$HostRootHandler.handleRequest(Host.java:430)
at io.undertow.server.handlers.NameVirtualHostHandler.handleRequest(NameVirtualHostHandler.java:54)
at io.undertow.server.handlers.error.SimpleErrorPageHandler.handleRequest(SimpleErrorPageHandler.java:78)
at io.undertow.server.handlers.CanonicalPathHandler.handleRequest(CanonicalPathHandler.java:49)
at org.wildfly.extension.undertow.Server$DefaultHostHandler.handleRequest(Server.java:190)
at io.undertow.server.handlers.ChannelUpgradeHandler.handleRequest(ChannelUpgradeHandler.java:211)
at io.undertow.server.protocol.http2.Http2UpgradeHandler.handleRequest(Http2UpgradeHandler.java:102)
at io.undertow.server.handlers.DisallowedMethodsHandler.handleRequest(DisallowedMethodsHandler.java:61)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:370)
at io.undertow.server.protocol.http.HttpReadListener.handleEventWithNoRunningRequest(HttpReadListener.java:255)
at io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:136)
at io.undertow.server.protocol.http.HttpOpenListener.handleEvent(HttpOpenListener.java:162)
at io.undertow.server.protocol.http.HttpOpenListener.handleEvent(HttpOpenListener.java:100)
at io.undertow.server.protocol.http.HttpOpenListener.handleEvent(HttpOpenListener.java:57)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.ChannelListeners$10.handleEvent(ChannelListeners.java:291)
at org.xnio.ChannelListeners$10.handleEvent(ChannelListeners.java:286)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.nio.QueuedNioTcpServer2.acceptTask(QueuedNioTcpServer2.java:178)
at org.xnio.nio.WorkerThread.safeRun(WorkerThread.java:612)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:479)
Resolution
This is a bug in the comparator implementation inside the undertow subsystem. The following JIRAs have been raised. This will be fixed in the future releases (tentatively EAP 7.2.9 and EAP 7.3.2):
- 7.3.z: <This content is not included.https://issues.redhat.com/browse/JBEAP-19449>
- 7.2.z: <This content is not included.https://issues.redhat.com/browse/JBEAP-19450>
- Upstream (WildFly): <This content is not included.https://issues.redhat.com/browse/WFLY-13447>
The sorting algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort has been replaced to TimSort algorithm since Java 7. And the TimSort algorithm will throw the IllegalArgumentException if it happens to detect inconsistency in the comparison, but it is not guaranteed to do so. (It also depends on the order of the internal array, so the exception does not always happen.)
And the current Java's TimSort implementation uses mini-TimSort with no merge when the size is smaller than 32. So, this issue does not happen when the number of filter-ref definitions is smaller than 32 because the IllegalArgumentException can happen only during the merge.
Therefore, if you can reduce the number of filter-ref definition to lower than 32, you can prevent facing this issue.
If you face this issue and you really need such many filter setting, you can work around this issue by adding the following to JAVA_OPTS in standalone.conf:
JAVA_OPTS="$JAVA_OPTS -Djava.util.Arrays.useLegacyMergeSort=true"
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.