Beim Versuch, PDFs zu importieren, erhalte ich bei einem Ordner mit Daten aus 2022 unmittelbar eine Fehlermeldung:
Error log:
Tue Dec 06 13:20:22 CST 2022
Internal Error
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.base/java.util.TimSort.mergeLo(Unknown Source)
at java.base/java.util.TimSort.mergeAt(Unknown Source)
at java.base/java.util.TimSort.mergeCollapse(Unknown Source)
at java.base/java.util.TimSort.sort(Unknown Source)
at java.base/java.util.Arrays.sort(Unknown Source)
at java.base/java.util.ArrayList.sort(Unknown Source)
at name.abuchen.portfolio.ui.handlers.ImportPDFHandler.runImportWithFiles(ImportPDFHandler.java:158)
at name.abuchen.portfolio.ui.handlers.ImportPDFHandler.runImport(ImportPDFHandler.java:136)
at name.abuchen.portfolio.ui.views.PortfolioListView.lambda$7(PortfolioListView.java:302)
at name.abuchen.portfolio.ui.util.SimpleAction.run(SimpleAction.java:69)
at org.eclipse.jface.action.Action.runWithEvent(Action.java:474)
at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:580)
at org.eclipse.jface.action.ActionContributionItem.lambda$4(ActionContributionItem.java:414)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4243)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1063)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4060)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3632)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1155)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1046)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:168)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:136)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:659)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:596)
at org.eclipse.equinox.launcher.Main.run(Main.java:1467)
Der Fehler scheint also aufzutreten an dieser Stelle:
public static void runImportWithFiles(PortfolioPart part, Shell shell, Client client, Account account,
Portfolio portfolio, List<File> files)
{
files.sort((File lhs, File rhs) -> {
int modDiff = (int) (lhs.lastModified() - rhs.lastModified());
return modDiff == 0 ? lhs.getPath().compareTo(rhs.getPath()) : modDiff;
});
//...
Jetzt habe ich bei mir diesen Codeblock lokal laufen lassen für den betroffenen Ordner:
List<File> files = Arrays.asList(new File("mydir").listFiles());
files.sort((File lhs, File rhs) -> {
int modDiff = (int) (lhs.lastModified() - rhs.lastModified());
return modDiff == 0 ? lhs.getPath().compareTo(rhs.getPath()) : modDiff;
});
Ergebnis: Die gleiche Exception tritt auf.
Der Grund scheint in einem Integer-Overflow zu liegen. Bei mir im Beispiel:
Der Sort-Aufruf sollte aus meiner Sicht wie folgt angepasst werden:
files.sort((File lhs, File rhs) -> {
int modDiff = Long.compare(lhs.lastModified(), rhs.lastModified());
return modDiff == 0 ? lhs.getPath().compareTo(rhs.getPath()) : modDiff;
});
oder:
files.sort(Comparator.comparing(File::lastModified).thenComparing(File::getPath));