Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 460618

Summary: JavaElementComparator: Comparison method violates its general contract (was: Trying to create new working set as part of an import fails (on Java8)
Product: [Eclipse Project] JDT Reporter: Thomas Schindl <tom.schindl>
Component: UIAssignee: JDT-UI-Inbox <jdt-ui-inbox>
Status: CLOSED WONTFIX QA Contact:
Severity: normal    
Priority: P3 CC: daniel_megert, error-reports-inbox, markus.kell.r, noopur_gupta, stephan.herrmann, timo.kinnunen
Version: 4.5   
Target Milestone: ---   
Hardware: PC   
OS: Mac OS X   
Whiteboard: stalebug
Attachments:
Description Flags
Small utility function testing that a Comparator implements its contract
none
Optimized utility function testing Comparator contract
none
Fixed and improved utility function testing Comparator contract none

Description Thomas Schindl CLA 2015-02-23 11:46:09 EST
java.lang.IllegalArgumentException: Comparison method violates its general contract!
	at java.util.TimSort.mergeHi(TimSort.java:895)
	at java.util.TimSort.mergeAt(TimSort.java:512)
	at java.util.TimSort.mergeCollapse(TimSort.java:437)
	at java.util.TimSort.sort(TimSort.java:241)
	at java.util.Arrays.sort(Arrays.java:1438)
	at org.eclipse.jface.viewers.ViewerComparator.sort(ViewerComparator.java:189)
	at org.eclipse.jface.viewers.AbstractTreeViewer.getSortedChildren(AbstractTreeViewer.java:640)
	at org.eclipse.jface.viewers.AbstractTreeViewer.updateChildren(AbstractTreeViewer.java:2647)
	at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefreshStruct(AbstractTreeViewer.java:1916)
	at org.eclipse.jface.viewers.TreeViewer.internalRefreshStruct(TreeViewer.java:684)
	at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1891)
	at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1848)
	at org.eclipse.jface.viewers.StructuredViewer$8.run(StructuredViewer.java:1554)
	at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1462)
	at org.eclipse.jface.viewers.TreeViewer.preservingSelection(TreeViewer.java:366)
	at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1423)
	at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1551)
	at org.eclipse.jface.viewers.ColumnViewer.refresh(ColumnViewer.java:534)
	at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1507)
	at org.eclipse.jdt.internal.ui.workingsets.AbstractWorkingSetWizardPage.createControl(AbstractWorkingSetWizardPage.java:223)
	at org.eclipse.jdt.internal.ui.workingsets.JavaWorkingSetPage.createControl(JavaWorkingSetPage.java:99)
	at org.eclipse.jface.wizard.WizardDialog.updateForPage(WizardDialog.java:1216)
	at org.eclipse.jface.wizard.WizardDialog.access$4(WizardDialog.java:1208)
	at org.eclipse.jface.wizard.WizardDialog$8.run(WizardDialog.java:1197)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
	at org.eclipse.jface.wizard.WizardDialog.showPage(WizardDialog.java:1194)
	at org.eclipse.ui.internal.dialogs.WorkingSetTypePage.handleDoubleClick(WorkingSetTypePage.java:200)
	at org.eclipse.ui.internal.dialogs.WorkingSetTypePage.access$1(WorkingSetTypePage.java:198)
	at org.eclipse.ui.internal.dialogs.WorkingSetTypePage$2.doubleClick(WorkingSetTypePage.java:123)
	at org.eclipse.jface.viewers.StructuredViewer$1.run(StructuredViewer.java:832)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:50)
	at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:173)
	at org.eclipse.jface.viewers.StructuredViewer.fireDoubleClick(StructuredViewer.java:829)
	at org.eclipse.jface.viewers.StructuredViewer.handleDoubleSelect(StructuredViewer.java:1150)
	at org.eclipse.jface.viewers.StructuredViewer$4.widgetDefaultSelected(StructuredViewer.java:1263)
	at org.eclipse.jface.util.OpenStrategy.fireDefaultSelectionEvent(OpenStrategy.java:252)
	at org.eclipse.jface.util.OpenStrategy.access$0(OpenStrategy.java:249)
	at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:311)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4200)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1467)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1490)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1475)
	at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1279)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4042)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3669)
	at org.eclipse.jface.window.Window.runEventLoop(Window.java:827)
	at org.eclipse.jface.window.Window.open(Window.java:803)
	at org.eclipse.ui.internal.dialogs.AbstractWorkingSetDialog.createWorkingSet(AbstractWorkingSetDialog.java:268)
	at org.eclipse.ui.internal.dialogs.AbstractWorkingSetDialog$1.widgetSelected(AbstractWorkingSetDialog.java:125)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:248)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4200)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1467)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1490)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1475)
	at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1279)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4042)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3669)
	at org.eclipse.jface.window.Window.runEventLoop(Window.java:827)
	at org.eclipse.jface.window.Window.open(Window.java:803)
	at org.eclipse.ui.internal.dialogs.AbstractWorkingSetDialog.open(AbstractWorkingSetDialog.java:313)
	at org.eclipse.ui.dialogs.WorkingSetConfigurationBlock$1.widgetSelected(WorkingSetConfigurationBlock.java:304)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:248)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4200)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1467)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1490)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1475)
	at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1279)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4042)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3669)
	at org.eclipse.jface.window.Window.runEventLoop(Window.java:827)
	at org.eclipse.jface.window.Window.open(Window.java:803)
	at org.eclipse.ui.internal.handlers.WizardHandler$Import.executeHandler(WizardHandler.java:158)
	at org.eclipse.ui.internal.handlers.WizardHandler.execute(WizardHandler.java:290)
	at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:295)
	at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:90)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:55)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:247)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:229)
	at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:132)
	at org.eclipse.e4.core.commands.internal.HandlerServiceHandler.execute(HandlerServiceHandler.java:149)
	at org.eclipse.core.commands.Command.executeWithChecks(Command.java:499)
	at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
	at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.executeHandler(HandlerServiceImpl.java:210)
	at org.eclipse.ui.internal.handlers.LegacyHandlerService.executeCommand(LegacyHandlerService.java:343)
	at org.eclipse.ui.internal.actions.CommandAction.runWithEvent(CommandAction.java:160)
	at org.eclipse.ui.internal.actions.CommandAction.run(CommandAction.java:175)
	at org.eclipse.ui.actions.ImportResourcesAction.run(ImportResourcesAction.java:99)
	at org.eclipse.ui.actions.BaseSelectionListenerAction.runWithEvent(BaseSelectionListenerAction.java:170)
	at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:595)
	at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:511)
	at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:420)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4200)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1467)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1490)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1475)
	at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1279)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4042)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3669)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1151)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:337)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1032)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:156)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:648)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:337)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:592)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:138)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:648)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:603)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1465)
Comment 1 Thomas Schindl CLA 2015-02-23 17:13:28 EST
moveing to JDT because the comparator is from them
Comment 2 Stephan Herrmann CLA 2015-02-23 17:49:19 EST
(In reply to Thomas Schindl from comment #1)
> moveing to JDT because the comparator is from them

Can you elaborate? 

As the stack trace doesn't really show any JDT owned comparator did you observe the situation in the debugger? Or did you infer via code inspection that probably a JavaElementComparator was involved? 

You also didn't say anything about reproducibility, steps and all that :)
Comment 3 Thomas Schindl CLA 2015-02-23 18:18:02 EST
I looked at the stack which mentions org.eclipse.jdt.internal.ui.workingsets.JavaWorkingSetPage and the comparator is set in JavaWorkingSetPage#configureTree and is of type JavaElementComparator
Comment 4 Thomas Schindl CLA 2015-02-23 18:19:23 EST
Looking at ViewerComparator I saw that it logs more data

Workaround for comparator violation:
	- set system property java.util.Arrays.useLegacyMergeSort=true
	- use a 1.6 JRE 
message: Comparison method violates its general contract!
this: org.eclipse.jdt.ui.JavaElementComparator
comparator: com.ibm.icu.text.RuleBasedCollator
array:
	> at.bestsolution.fx.slide.show  [fxslide NO-HEAD]
	> at.bestsolution.fx.slide.show.sample  [fxslide NO-HEAD]
	> jfxextras  [jfxtras 8.0]
	> miglayout  [miglayout master]
	at.bestsolution.efxclipse.animation.pop
	at.bestsolution.efxclipse.jemmy  [efxclipse_addons master]
	at.bestsolution.fx.slide.dsl
	at.bestsolution.fx.slide.dsl.tests
	at.bestsolution.fx.slide.dsl.ui
	at.bestsolution.fx.slide.model
	at.bestsolution.fx.slide.model.ecore
	bbb
	bbb.tests
	CompilerTest
	controlsfx
	controlsfx-samples
	dummy.app
	dummy.app.jemmy
	External Plug-in Libraries
	fxsampler
	FXTest
	nnnnn
	org.eclipse.fx.core  [efxclipse master]
	org.eclipse.fx.core.databinding  [efxclipse master]
	org.eclipse.fx.core.databinding.tests  [efxclipse master]
	org.eclipse.fx.core.di  [efxclipse master]
	org.eclipse.fx.core.di.context  [efxclipse master]
	org.eclipse.fx.core.di.context.tests  [efxclipse master]
	org.eclipse.fx.core.fxml  [efxclipse master]
	org.eclipse.fx.core.guice  [efxclipse master]
	org.eclipse.fx.core.log4j  [efxclipse master]
	org.eclipse.fx.core.p2  [efxclipse master]
	org.eclipse.fx.core.slf4j  [efxclipse master]
	org.eclipse.fx.demo.contacts  [efxclipse master]
	org.eclipse.fx.demo.contacts.app  [efxclipse master]
	org.eclipse.fx.demo.contacts.edit  [efxclipse master]
	org.eclipse.fx.demo.contacts.edit.tests  [efxclipse master]
	org.eclipse.fx.emf.databinding  [efxclipse master]
	org.eclipse.fx.emf.edit.ui  [efxclipse master]
	org.eclipse.fx.formats.svg  [efxclipse master]
	org.eclipse.fx.ide.ant  [efxclipse master]
	org.eclipse.fx.ide.converter  [efxclipse master]
	org.eclipse.fx.ide.css  [efxclipse master]
	org.eclipse.fx.ide.css.controlsfx
	org.eclipse.fx.ide.css.cssext  [efxclipse master]
	org.eclipse.fx.ide.css.cssext.proposals  [efxclipse master]
	org.eclipse.fx.ide.css.cssext.tests  [efxclipse master]
	org.eclipse.fx.ide.css.cssext.ui  [efxclipse master]
	org.eclipse.fx.ide.css.jfx  [efxclipse master]
	org.eclipse.fx.ide.css.jfx2  [efxclipse master]
	org.eclipse.fx.ide.css.jfx8  [efxclipse master]
	org.eclipse.fx.ide.css.jfxextras
	org.eclipse.fx.ide.css.tests  [efxclipse master]
	org.eclipse.fx.ide.css.ui  [efxclipse master]
	org.eclipse.fx.ide.fxgraph  [efxclipse master]
	org.eclipse.fx.ide.fxgraph.tests  [efxclipse master]
	org.eclipse.fx.ide.fxgraph.ui  [efxclipse master]
	org.eclipse.fx.ide.fxml  [efxclipse master]
	org.eclipse.fx.ide.fxml.compiler  [efxclipse master]
	org.eclipse.fx.ide.java6  [efxclipse master]
	org.eclipse.fx.ide.jdt.core  [efxclipse master]
	org.eclipse.fx.ide.jdt.ui  [efxclipse master]
	SampleForMobile
	TestFXSample
	TestNull
	> org.eclipse.fx.ide.l10n  [efxclipse master]
	> org.eclipse.fx.ide.l10n.ui  [efxclipse master]
	org.eclipse.fx.ide.l10n.tests  [efxclipse master]
	org.eclipse.fx.ide.model  [efxclipse master]
	org.eclipse.fx.ide.pde.core  [efxclipse master]
	org.eclipse.fx.ide.pde.java7  [efxclipse master]
	org.eclipse.fx.ide.pde.ui  [efxclipse master]
	org.eclipse.fx.ide.pde.ui.e4  [efxclipse master]
	org.eclipse.fx.ide.rrobot  [efxclipse master]
	org.eclipse.fx.ide.rrobot.dsl  [efxclipse master]
	org.eclipse.fx.ide.rrobot.dsl.tests  [efxclipse master]
	org.eclipse.fx.ide.rrobot.dsl.ui  [efxclipse master]
	org.eclipse.fx.ide.rrobot.model  [efxclipse master]
	org.eclipse.fx.ide.ui  [efxclipse master]
	org.eclipse.fx.ide.ui.mobile.sim.device  [efxclipse master]
	org.eclipse.fx.ide.ui.mobile.sim.launch  [efxclipse master]
	org.eclipse.fx.ide.ui.preview  [efxclipse master]
	org.eclipse.fx.javafx  [efxclipse master]
	org.eclipse.fx.osgi  [efxclipse master]
	org.eclipse.fx.osgi.util  [efxclipse master]
	org.eclipse.fx.runtime.doc  [efxclipse master]
	> org.eclipse.fx.runtime.swt  [efxclipse master]
	BlaBlaBla
	BlaBlaBlaBla
	Blum
	DummyJavaFX
	HHHHH
	InferenceProblem
	MySample.app
	MySample.app.feature
	org.eclipse.fx.shared.doc
	org.eclipse.fx.testcases.e4
	org.eclipse.fx.ui.animation
	org.eclipse.fx.ui.controls
	org.eclipse.fx.ui.controls.sample
	org.eclipse.fx.ui.databinding
	org.eclipse.fx.ui.di
	org.eclipse.fx.ui.di.interopt
	org.eclipse.fx.ui.dialogs
	org.eclipse.fx.ui.keybindings
	org.eclipse.fx.ui.keybindings.e4
	org.eclipse.fx.ui.keybindings.generic
	org.eclipse.fx.ui.mobile
	org.eclipse.fx.ui.mobile.sensors.api
	org.eclipse.fx.ui.modelviewer
	org.eclipse.fx.ui.panes
	org.eclipse.fx.ui.services
	org.eclipse.fx.ui.theme
	org.eclipse.fx.ui.viewer
	org.eclipse.fx.ui.viewer.demo
	org.eclipse.fx.ui.viewer.javafx
	org.eclipse.fx.ui.workbench.base
	org.eclipse.fx.ui.workbench.fx
	org.eclipse.fx.ui.workbench.renderers.base
	org.eclipse.fx.ui.workbench.renderers.fx
	org.eclipse.fx.ui.workbench.services
	org.eclipse.fx.ui.workbench3
	org.eclipse.jdt.nullanalysis
	org.eclipse.jdt.nullanalysis.tests
	org.eclipse.jdt.nullanalysis.ui
	org.jemmy.fx.repackaged
	sssss
	MySample.app.jemmy
	MySample.app.jemmy.feature
	MySample.app.product
	MySample.app.releng
	Sample
	SampleJ8
	SampleProject
	Samplemedia
	Samplemedia.feature
	Samplemedia.product
	Test
	TestDND
	TestFX
	TestJ7
	TestJ8
	TestJ8Plugin
	TestLayout
	TestMe
	TestSWT
	addons_homepage
	at.bestsolution.efxclipse.jemmy.feature
	at.bestsolution.efxclipse.jemmy.junit.feature
	at.bestsolution.efxclipse.less
	at.bestsolution.efxclipse.less.feature
	at.bestsolution.efxclipse.releng
	at.bestsolution.efxclipse.releng.assembler
	at.bestsolution.efxclipse.robovm
	at.bestsolution.efxclipse.robovm.feature
	at.bestsolution.efxclipse.updatesite
	at.bestsolution.fx.slide.dsl.sdk
	at.bestsolution.lego
	at.bestsolution.lego.elements
	at.bestsolution.lego.sdk
	at.bestsolution.lego.tests
	at.bestsolution.lego.ui
	at.bestsolution.swt.css
	bbbb
	bla.bla.app
	bla.bla.app.feature
	bla.bla.app.product
	bla.bla.app.releng
	blabla
	dummy.app.feature
	dummy.app.jemmy.feature
	dummy.app.product
	dummy.app.releng
	efxclipse_homepage
	hgh
	maven-deploy
	org.eclipse.fx.code.compensator.hsl
	org.eclipse.fx.code.compensator.hsl.sdk
	org.eclipse.fx.code.compensator.hsl.tests
	org.eclipse.fx.code.compensator.hsl.ui
	org.eclipse.fx.core.feature
	org.eclipse.fx.core.shared.feature
	org.eclipse.fx.core.shared.updatesite
	org.eclipse.fx.demo.media
	org.eclipse.fx.emf.edit.ui.tests
	org.eclipse.fx.experimental.releng
	org.eclipse.fx.experimental.updatesite
	org.eclipse.fx.ide.basic.feature
	org.eclipse.fx.ide.compiler.releng
	org.eclipse.fx.ide.converter.feature
	org.eclipse.fx.ide.css.cssext.ui.debug
	org.eclipse.fx.ide.css.feature
	org.eclipse.fx.ide.feature
	org.eclipse.fx.ide.fxgraph.feature
	org.eclipse.fx.ide.fxml.feature
	org.eclipse.fx.ide.l10n.feature
	org.eclipse.fx.ide.mobile.feature
	org.eclipse.fx.ide.pde.feature
	org.eclipse.fx.ide.releng
	org.eclipse.fx.ide.rrobot.feature
	org.eclipse.fx.ide.updatesite
	org.eclipse.fx.releng
	org.eclipse.fx.releng.devsetup
	org.eclipse.fx.runtime.e4fx.feature
	org.eclipse.fx.runtime.examples.swt
	org.eclipse.fx.runtime.feature
	org.eclipse.fx.runtime.min.feature
	org.eclipse.fx.runtime.swt.compat
	org.eclipse.fx.samples.fxml.compiler
	org.eclipse.fx.shared.releng
	org.eclipse.fx.swtfx.feature
	org.eclipse.fx.target.feature
	org.eclipse.fx.target.rcp.feature
	org.eclipse.fx.target.rcp4.feature
	org.eclipse.fx.testcases.dnd.app
	org.eclipse.fx.testcases.dnd.app.feature
	org.eclipse.fx.testcases.dnd.app.jemmy
	org.eclipse.fx.testcases.dnd.app.jemmy.feature
	org.eclipse.fx.testcases.dnd.app.product
	org.eclipse.fx.testcases.dnd.app.releng
	org.eclipse.fx.testcases.l10n.app
	org.eclipse.fx.testcases.l10n.app.feature
	org.eclipse.fx.testcases.l10n.app.product
	org.eclipse.fx.testcases.l10n.app.releng
	org.eclipse.fx.ui.controls.demo
	org.eclipse.fx.ui.panes.demo
	org.eclipse.fx.updatesite
	org.eclipse.jdt.annotation_v1
	org.eclipse.jdt.nullanalysis.sdk
	org.eclipse.osgi
	org.eclipse.simrel.build
	org.eclipse.wst.sse.ui
	org.eclipse.xtext.example.domainmodel
	org.eclipse.xtext.example.domainmodel.tests
	org.eclipse.xtext.example.domainmodel.ui
	test.app
	test.app.feature
	test.app.product
	test.app.releng
	twemoji
	window-context-activation.app
	window-context-activation.app.feature
	window-context-activation.app.product
Comment 5 Dani Megert CLA 2015-02-24 06:51:29 EST
Steps would be nice.
Comment 6 Markus Keller CLA 2015-02-24 10:21:04 EST
Tom, can you reproduce the problem?

I don't see anything wrong in the JavaElementComparator, but I know that such problems are notoriously hard to find.

It's strange that the exception happens in
AbstractWorkingSetWizardPage.createControl(AbstractWorkingSetWizardPage.java:223)
in the call to "fTree.refresh(true);" and not already on line 212 in "createTree(leftComposite);", where the initial sorting takes place.

Could it be that you were checking out projects or switching branches in the background?

I don't get an exception when I try to sort the project names from comment 4 using ICU's Collator.getInstance(), so I think ICU is fine. I removed the "> " and "  [...]", since they are just artifacts of the label provider, but not used while sorting.
Comment 7 Thomas Schindl CLA 2015-02-24 11:47:56 EST
Unfortunately today I can not reproduce it (although I'm doing exactly the same i did yesterday), I was not checking out stuff but tried to import some samples from a zip file.
Comment 8 Markus Keller CLA 2015-02-25 06:54:30 EST
Please reopen if you have further information.
Comment 9 Dani Megert CLA 2015-06-01 07:30:35 EDT
*** Bug 468921 has been marked as a duplicate of this bug. ***
Comment 10 Timo Kinnunen CLA 2015-06-02 10:11:24 EDT
(In reply to comment #6)
> I don't get an exception when I try to sort the project names from comment 4
> using ICU's Collator.getInstance(), so I think ICU is fine. I removed the "> "
> and "  [...]", since they are just artifacts of the label provider, but not used
> while sorting.

I think they are used in sorting after all. JavaElementComparator calls getNonJavaElementLabel() method, which for ContentViewers calls their label provider's getText() method with the element. The default label provider simply returns what the element's toString() method is returning. JavaElementComparator then compares two such strings with each other and returns the result. This same procedure is followed in ViewerComparator's debug printing code, so the fact that labels beginning with the "> " prefix appear in the printed array strongly suggests such prefixes can influence the sort.

The array looks to be partially sorted. In particular, these items are in the correct order and they are at very start of the array:

	> at.bestsolution.fx.slide.show  [fxslide NO-HEAD]
	> at.bestsolution.fx.slide.show.sample  [fxslide NO-HEAD]
	> jfxextras  [jfxtras 8.0]
	> miglayout  [miglayout master]
	at.bestsolution.efxclipse.animation.pop
	
In contrast, these lines look very suspicious to me:

	org.eclipse.fx.osgi  [efxclipse master]
	org.eclipse.fx.osgi.util  [efxclipse master]
	org.eclipse.fx.runtime.doc  [efxclipse master]
	> org.eclipse.fx.runtime.swt  [efxclipse master]
	org.eclipse.fx.shared.doc
	org.eclipse.fx.testcases.e4
	org.eclipse.fx.ui.animation

If not for that one project in the middle these items would already be correctly sorted with respect to each other. Perhaps the org.eclipse.fx.runtime.swt project was refreshed in the middle of the sort, causing its toString() to change and causing an already sorted region of the array to break in the middle.
Comment 11 Dani Megert CLA 2015-06-02 10:49:52 EDT
.
Comment 12 Markus Keller CLA 2015-06-02 13:49:56 EDT
(In reply to Timo Kinnunen from comment #10)
> I think they are used in sorting after all. JavaElementComparator calls
> getNonJavaElementLabel() method, which for ContentViewers calls their label
> provider's getText() method with the element.

Not in this case. The "if (viewer instanceof ContentViewer)" is just a last-resort branch. When sorting IJavaProjects, it first gets the IWorkbenchAdapter, which is a JavaWorkbenchAdapter whose getLabel(..) method uses JavaElementLabels#getTextLabel(..). I.e. the undecorated project name.


To get to the bottom of this, we could better instrument the situation in ViewerComparator#sort(..). Instead of just logging the problem, we could:

a) retry the Arrays.sort(..) call. If it doesn't fail the second time, then it's an unstable comparator or the elements to be sorted return unstable data.

b) implement a trivial insertion sort as a fallback. During the sort, verify validity of the comparator and report the actual breakage (unlike TimSort's unhelpfully general "Comparison method violates its general contract!" message).

Once (b) is implemented, we can even avoid throwing an exception and just log the problem and then continue, even if the elements are not fully ordered in the end (like it was before Java 7).
Comment 13 Timo Kinnunen CLA 2015-06-04 12:19:45 EDT
Created attachment 254118 [details]
Small utility function testing that a Comparator implements its contract

Here is a smallish utility function which can be used to test that a Comparator implements its contract correctly. Specifically, that:

"The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y. The implementor must also ensure that the relation is transitive: ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0. Finally, the implementor must ensure that compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z."

For a given set of objects, it exhaustively checks that the original Comparator satisfies the compareTo method contract for every possible input combination.

The returned Comparator wraps the original and checks that all compared objects have been seen previously (that is, a collection is not modified concurrently) and that the original Comparator returns consistent results. For example, it can be installed in ViewerComparator like this:

Arrays.sort(elements, ComparatorContract.enforce(elements, o -> getLabel(viewer, o), new Comparator() {
@Override
public int compare(Object a, Object b) {
return ViewerComparator.this.compare(viewer, a, b);
}
}));
Comment 14 Markus Keller CLA 2015-06-04 14:22:55 EDT
(In reply to Timo Kinnunen from comment #13)
> Created attachment 254118 [details]
> Small utility function testing that a Comparator implements its contract

Thanks Timo, that looks very helpful!

The exhaustive check would be interesting for small and reproducible use cases.
Unfortunately there are two problems that make it unacceptable for general use in the ViewerComparator:

(1) The index into "byte[] results" starts to overflow at Math.sqrt(Integer.MAX_VALUE), i.e. 46341 elements

(2) O(n^3) performance means it already needs 4s to check 1000 elements:

    public static void main(String[] args) {
        int N= 1000;
        Object[] a= Stream.iterate(N, x -> x - 1).limit(N).toArray();
        Comparator<Object> sort= (x, y) -> (Integer) x - (Integer) y;

        System.out.println(Arrays.asList(a));
        time("sort:    ", () -> Arrays.sort(a, sort));
        System.out.println(Arrays.asList(a));
        time("enforce: ", () -> ComparatorContract.enforce(a, Object::toString, sort));
        System.out.println(Arrays.asList(a));
    }

    static void time(String label, Runnable runnable) {
        long start= System.currentTimeMillis();
        runnable.run();
        long time= System.currentTimeMillis() - start;
        System.out.println(label + time);
    }

Moreover, I think a single witness would usually be enough to pinpoint a problem in the comparator. That's why I suggested to go with a simple sorting algorithm that would still be reasonably quick and that could even run to the end and result in an "almost" sorted array like in Java < 7.
Comment 15 Timo Kinnunen CLA 2015-06-05 14:08:37 EDT
Created attachment 254154 [details]
Optimized utility function testing Comparator contract

Good points all around. This is an optimized version of the utility function. On my machine the old version took ~5000ms to run on 1000 items, this one takes about 78ms on a first run and about 30ms on the runs after that. This improvement over time is probably due to JIT compilation.

Unfortunately the O(N^3) nature still means that more than 2000 items takes more than 100ms which is not good for UI use. Dropping checks to get to O(N^2) gives us up to about 10000-20000 items, taking ~1sec while still catching any unstable comparisons. Beyond that requires further optimizations or changing the algorithm. Or just skipping the enforcement for such large views.

Also there's no more integer overflow but w/e :)
Comment 16 Timo Kinnunen CLA 2015-06-06 08:47:32 EDT
Created attachment 254160 [details]
Fixed and improved utility function testing Comparator contract

This version fixes a bug and improves generated messages by showing the indexes of the involved compared objects in the array being sorted. This helps in case their labels are exactly the same.

I've also filed Bug 469547 for JDT UI and Bug 469548 for Mylyn for the problems revealed so far. No sign of this one yet, though.
Comment 17 Eclipse Genie CLA 2020-05-07 09:45:46 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.