Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.util.NoSuchElementException raised when switching between "Sell BTC" and "Buy BTC" tabs #995

Closed
naortega opened this issue Nov 6, 2017 · 13 comments
Labels

Comments

@naortega
Copy link

naortega commented Nov 6, 2017

I got this exception while switching to the "Sell BTC" and "Buy BTC" tabs. I'd also like to note that this happened directly after I had been disconnected from all my P2P peers and had to reconnect (I reconnected and then started getting these errors).

Here's the stack trace from the bisq.log:

Nov-06 12:20:19.934 [JavaFX Application Thread] INFO  i.b.g.a.BisqApp: System load: Memory (MB)): 401 / No. of threads: 50 
Nov-06 12:22:07.978 [JavaFX Application Thread] ERROR i.b.g.a.BisqApp: Uncaught Exception from thread JavaFX Application Thread 
Nov-06 12:22:07.979 [JavaFX Application Thread] ERROR i.b.g.a.BisqApp: throwableMessage= null 
Nov-06 12:22:07.979 [JavaFX Application Thread] ERROR i.b.g.a.BisqApp: throwableClass= class java.util.NoSuchElementException 
Nov-06 12:22:07.980 [JavaFX Application Thread] ERROR i.b.g.a.BisqApp: Stack trace:
java.util.NoSuchElementException
	at java.util.AbstractList$Itr.next(AbstractList.java:364)
	at java.util.AbstractCollection.toArray(AbstractCollection.java:141)
	at java.util.ArrayList.<init>(ArrayList.java:177)
	at javafx.collections.transformation.FilteredList.refilter(FilteredList.java:320)
	at javafx.collections.transformation.FilteredList.access$000(FilteredList.java:50)
	at javafx.collections.transformation.FilteredList$1.invalidated(FilteredList.java:102)
	at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:111)
	at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
	at javafx.collections.transformation.FilteredList.setPredicate(FilteredList.java:125)
	at io.bisq.gui.main.offer.offerbook.OfferBookViewModel.applyFilterPredicate(OfferBookViewModel.java:421)
	at io.bisq.gui.main.offer.offerbook.OfferBookViewModel.activate(OfferBookViewModel.java:156)
	at io.bisq.gui.common.model.ActivatableViewModel._activate(ActivatableViewModel.java:28)
	at io.bisq.gui.common.view.ActivatableViewAndModel.lambda$prepareInitialize$0(ActivatableViewAndModel.java:41)
	at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
	at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
	at javafx.beans.property.ReadOnlyObjectPropertyBase.fireValueChangedEvent(ReadOnlyObjectPropertyBase.java:74)
	at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:102)
	at javafx.scene.Node$ReadOnlyObjectWrapperManualFire.fireSuperValueChangedEvent(Node.java:831)
	at javafx.scene.Node.invalidatedScenes(Node.java:883)
	at javafx.scene.Node.setScenes(Node.java:921)
	at javafx.scene.Parent.scenesChanged(Parent.java:667)
	at javafx.scene.Node.invalidatedScenes(Node.java:855)
	at javafx.scene.Node.setScenes(Node.java:921)
	at javafx.scene.Parent.scenesChanged(Parent.java:667)
	at javafx.scene.Node.invalidatedScenes(Node.java:855)
	at javafx.scene.Node.setScenes(Node.java:921)
	at javafx.scene.Parent$1.onChanged(Parent.java:269)
	at com.sun.javafx.collections.TrackableObservableList.lambda$new$19(TrackableObservableList.java:45)
	at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
	at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
	at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
	at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
	at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
	at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
	at javafx.collections.ModifiableObservableListBase.setAll(ModifiableObservableListBase.java:90)
	at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:116)
	at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
	at io.bisq.gui.main.MainView.lambda$initialize$8(MainView.java:237)
	at io.bisq.gui.Navigation.lambda$navigateTo$2(Navigation.java:123)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
	at io.bisq.gui.Navigation.navigateTo(Navigation.java:123)
	at io.bisq.gui.Navigation.navigateTo(Navigation.java:92)
	at io.bisq.gui.main.MainView$NavButton.lambda$new$1(MainView.java:661)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Node.fireEvent(Node.java:8413)
	at javafx.scene.control.ToggleButton.fire(ToggleButton.java:256)
	at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
	at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
	at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
	at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
	at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
	at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
	at com.sun.glass.ui.View.notifyMouse(View.java:937)
	at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
	at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)
	at java.lang.Thread.run(Thread.java:748)
 

Upon restarting Bisq I no longer seem to get this error.

@cbeams
Copy link
Contributor

cbeams commented Nov 15, 2017

Looks like this may be the same bug @meapistol mentioned in #868.

@cbeams cbeams changed the title java.util.NoSuchElementException java.util.NoSuchElementException raised when switching between "Sell BTC" and "Buy BTC" tabs Nov 15, 2017
@naortega
Copy link
Author

naortega commented Nov 16, 2017 via email

@ghost
Copy link

ghost commented Dec 2, 2017

Wow, it looks like async collection modify error, because occured in new Array(c) during OfferBookViewModel activation, and exactly during cloning underlying filteredItems collection with order book items.

image

Similar problems were detected for Viritin and also around lazy and filter wrappers: viritin/viritin#273, https://vaadin.com/forum#!/thread/11721719.

I will try to reproduce it via async modify...

@ghost
Copy link

ghost commented Dec 2, 2017

@Deathsbreed it occured only once or was reproducible several times before disappearing?

@ghost
Copy link

ghost commented Dec 2, 2017

This error also can be related to JDK - https://bugs.openjdk.java.net/browse/JDK-8161558

@ghost
Copy link

ghost commented Dec 2, 2017

Yes, it's reproducible!

OfferBookModelView.java:

    private void applyFilterPredicate() {
+++        new Thread(){
+++            public void run(){
+++                filteredItems.getSource().remove(0);
+++            }
+++        }.start();
        filteredItems.setPredicate(offerBookListItem -> {
            Offer offer = offerBookListItem.getOffer();
            boolean directionResult = offer.getDirection() != direction;
            boolean currencyResult = showAllTradeCurrenciesProperty.get() ||
                    offer.getCurrencyCode().equals(selectedTradeCurrency.getCode());
            boolean paymentMethodResult = showAllPaymentMethods ||
                    offer.getPaymentMethod().equals(selectedPaymentMethod);
            boolean notMyOfferOrShowMyOffersActivated = !isMyOffer(offerBookListItem.getOffer()) || preferences.isShowOwnOffersInOfferBook();
            return directionResult && currencyResult && paymentMethodResult && notMyOfferOrShowMyOffersActivated;
        });
    }

image

and similar exception.

@ghost
Copy link

ghost commented Dec 2, 2017

My resolution for this bug - the error in JavaFX's FilterList iml., because it wraps original ObservableList collection, but not correctly handles update in an underlying collection and change the size property between follow iteration calls and thus corrupt Iteration internal logic asserts:

        for (int i = 0; i < r.length; i++) {
>>>            if (! it.hasNext()) // fewer elements than expected
                return Arrays.copyOf(r, i);
>>>            r[i] = it.next();
        }

Additionally, occurred not java.util.NoSuchElementException, but java.lang.IndexOutOfBoundsExceptions instead (open JDK issue, registered here).

image

I listed in code all possible places where performed offerBookListItems updates and I think that one possible work around is to add some synchronization logic (usually not good because of performance penalties) in order to protect concurrent access, but normally all collection updates are performed from the single JavaFX UI thread, so looks strange right now.

The problem is to protect the OfferBookViewModel.applyFilterPredicate method call from concurrent updates from external threads:

    private void applyFilterPredicate() {
here occurs the error >>>        filteredItems.setPredicate(offerBookListItem -> {
...
    }

For me it's not clear how to fix that JavaFX behavior, if I will find solution I come back and write about it.

@ghost
Copy link

ghost commented Dec 2, 2017

@ManfredKarrer I think somewhere in the code there is a place where an offerBookListItems collection is modified not from the JavaFX UI thread (Platform.runLater(() -> ...)), but it's quite difficult to find. May be somewhere in peer network re-connection logic.

@ManfredKarrer
Copy link
Contributor

@dulanov Thanks a lot for your investigation!

The list should be only accessed via UI thread.
The underlying list get modified in OfferBook at offerBookService.addOfferBookChangedListener but the callbacks there are mapped to the UI thread.

I tried the remove within a thread as you posted above but that does not reproduce the issue for me. With the live data though I get a ConcurrentModificationException when doing that.

@ManfredKarrer
Copy link
Contributor

I put a log into the onAdded and onRemoved calls in OfferBook to log the calling thread (so far its all UI thread). Also a try/catch for the applyFilterPredicate. Will leave it running a while so see if I can reproduce it.

@ghost
Copy link

ghost commented Dec 2, 2017

Usually occurs ConcurrentModificationException but time to time also NoSuchElementException.

I also tried to find an update not from JavaFX Thread via using conditional breakpoints and additionally set uped automatic switch between first three NavButtons (every 300 ms), but without success. May be it's not reproducible on my Window machine (occurred on Linux, because at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)).

image

@ManfredKarrer
Copy link
Contributor

Yes maybe it is a Linux issue. The UI implementation of JavaFX on Linux is always a bit more problematic than other OS. I also never saw that exception myself (OSX). Might be also that is is fixed in Java 9. If maven supports Java9 at next release time we will update as well.

@ripcurlx
Copy link
Contributor

Closed because of added Java 10 support. Please re-open this issue, if it still occurs with current master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants