Under certain conditions, SNT usage can trigger a bug in the JDK1.8 currently bundled within Fiji.
It is a bug in java.util.TimSort
, in this case triggered by a com.jogamp.opengl
class call. In the context of SNT usage, the bug can be just ‘annoying’ (e.g. linux with jdk1.8.0_172) or catastrophic: with an earlier jdk 1.8 version, the JVM segfaults and Fiji crashes. It is that nasty.
Exception in thread "SciJava-4b2a01d4-Thread-11-AWTAnimator#00" com.jogamp.opengl.util.AnimatorBase$UncaughtAnimatorException: com.jogamp.opengl.GLException: Caught IllegalArgumentException: Comparison method violates its general contract! on thread SciJava-4b2a01d4-Thread-11-AWTAnimator#00
at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:92)
at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:452)
at com.jogamp.opengl.util.Animator$MainLoop.run(Animator.java:204)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.jogamp.opengl.GLException: Caught IllegalArgumentException: Comparison method violates its general contract! on thread SciJava-4b2a01d4-Thread-11-AWTAnimator#00
at com.jogamp.opengl.GLException.newGLException(GLException.java:76)
at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1327)
at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147)
at com.jogamp.opengl.awt.GLCanvas$12.run(GLCanvas.java:1438)
at com.jogamp.opengl.Threading.invoke(Threading.java:223)
at com.jogamp.opengl.awt.GLCanvas.display(GLCanvas.java:505)
at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81)
... 3 more
Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:899)
at java.util.TimSort.mergeAt(TimSort.java:516)
at java.util.TimSort.mergeForceCollapse(TimSort.java:457)
at java.util.TimSort.sort(TimSort.java:254)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1462)
at java.util.Collections.sort(Collections.java:175)
The issue is discussed, e.g., here (triggered by swing code on java 1.7 but the consequences are the same). The solutions proposed on that SO thread work, namely:
-
call
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true")
-
setting
-Djava.util.Arrays.useLegacyMergeSort=true
at startup
I don’t think it is possible to set #2 on our end. But we could certainly implement #1, however. There are two issues with that:- It will only work when users start SNT right after starting Fiji. If users run any Java code that calls
java.util.Arrays
, before starting SNT, setting the property will do nothing. - Setting the property will disable Timsort which is more efficient than legacy sorting. If we do disable it, won’t we degrade the performance of Fiji for SNT users?
- It will only work when users start SNT right after starting Fiji. If users run any Java code that calls
Presumably, this issue is moot on the latest version of JDK 1.8 241 (i have yet to formally test it, but it appears to be fixed), so updating the JDK would also be an option (albeit users would have to download a new Fiji.app). I know the future of the bundled JDK is discussed here, but we need and immediate/short-term solution.
I guess another option would be to nag users (e.g., at startup) to update their jdk, or at least download a newer Fiji.app with jdk1.8.0_172 in which the bug is not as severe. Not sure if that is an effective workaround.
I am actually surprised that nodoby came across this in the past. I guess everybody is developing with newer JDK versions? What do you guys advise?
(Pinging @imagejan, @hinerm , @ctrueden, but please do chime in if you have any insights)