Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
Randomly IllegalMonitorStateException. How to find the error?
since switching to Vaadin 7.7.5 we getting some times and radomly IllegalMonitorStateException in
Exception: java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261) at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457) at com.coco_on.docFlow.vaadin.MainWorkView.refreshAll(MainWorkView.java:427) ...
We working much with "Please wait" dialogs, so we have often background (worker) Threads. While updating the UI we use the UI.access(...) method to make sure that we are changing the UI in (hopefully) every case from a "valid" thread. But may be we calling also the UI.access(...) method if we are already in the "vaadin UI" thread (may be this is also a part of the problem?). The call of MainWorkView.refreshAll(...) is already inside of a UI.access-Runnable (see above StackTrace).
At the moment we getting the exception while a (very) complex view will be shown. For us it's very difficult to find out what's the problem is ....
Whats the recommendet way to find the problem of the IllegalMonitorStateException? Why is this thrown while releasing the Lock (after looking at the Vaadin code I asume that the MonitorState must be already illegal while set the lock). Can be a forgetten "UI.access(...)" call the reason of this Exception? Any tipps for searching the error are welcome.
Here another StackTrace:
Exception: java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261) at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457) at com.vaadin.server.VaadinSession.unlock(VaadinSession.java:1008) at com.vaadin.server.VaadinService.ensureAccessQueuePurged(VaadinService.java:1809) at com.vaadin.server.VaadinService.accessSession(VaadinService.java:1775) at com.vaadin.server.VaadinSession.access(VaadinSession.java:1384) at com.vaadin.ui.UI.access(UI.java:1460) at com.coco_on.docFlow.vaadin.util.DocFlowViewComponent.doOk(DocFlowViewComponent.java:444)
Seem's we found was wrong.
We have found different lines in our code were we use the old synchronizing mechanism with
getSession().getLockInstance().lock(); // here we do something secret things ;-) getSession().getLockInstance().unlock();
This is coming from a time we are using Vaadin 6.* or Vaadin 7.0. The UI.access() method is available sinc Vaadin 7.1.
Seems that this don't works together with the access() method. This is because the access() method will be released the same Lock object a second time by caling unlock() again.
So the solution is for us to remove all 'getSession().getLockInstance().lock()/.unlock()'.
Hi Steffen, to verify whether you really are accessing Vaadin code from a properly locked code only, please start your server with -ea (enable assertions). Lots of Vaadin code (though not all) is protected by a call to
for example every piece of code which calls the VaadinSession class is protected by such call. This way you might be able to spot Vaadin code accessed from outside of the session lock.
Regarding to the synchronization mechanism: this is a bit weird. From the behaviour you described I judge that the access() method unlocks the lock more times than it locks the lock. If this is true then there is definitely a bug in Vaadin: the access() method should either not lock at all (if some other thread has the session locked), or it should lock+unlock exactly once. Which version of Vaadin are you using?