- IllegalMonitorStateException
- 4 Answers 4
- Resolving IllegalMonitorStateException In Java
- How to Handle the Illegal Monitor State Exception in Java
- What Causes IllegalMonitorStateException
- IllegalMonitorStateException Example
- How to Resolve IllegalMonitorStateException
- Track, Analyze and Manage Errors With Rollbar
IllegalMonitorStateException
When running our program we get an exception of type java.lang.IllegalMonitorStateException. On Java6 API website, it says there is a constructor that gives a details about the exception: IllegalMonitorStateException(String s) How can we use this to get a better idea of where the bug is in our code? Is there anything else we can do (besides lots of debugging which we’re currently doing) to pinpoint the function or line that failed?
4 Answers 4
The details must be given when the Exception is created (Constructor, right?) and if you are not creating it, there is no way for you to provide the details.
You can analize the StackTrace of the Exception. It shows the classes, methods and souce line which were called to cause the Exception.
One cause for the IllegalMonitorStateException is trying to wait on an Object without having synchronized on it. See the Javadoc.
There are other possible causes and the Exception may be thrown by some library/external code. I think only the StackTrace can help.
This is maybe occurring because the instance of the object which you are calling wait or notify on is different that the instance you synchronized with. For example:
Integer a; a = new Integer(0); synchronized(a)
This will throw the IllegalMonitorStateException because the instance that ‘a’ points to is no longer the same.
How can we use this to get a better idea of where the bug is in our code? Is there anything else we can do (besides lots of debugging which we’re currently doing) to pinpoint the function or line that failed?
In this case, printing the message by itself probably won’t help much. What you need is a stacktrace with source file names and line numbers.
- Make sure that all relevant «.class» files / JARs were built with file and line number debug information included. This is the default, but compiling with «-g:none» will strip this . as will most JAR file obfuscators.
- Next, add a try / catch block to catch the IllegalMonitorStateException and either call ex.printStackTrace() or log the exception.
From the stacktrace you should be able to see what line in the code threw the exception. The chances are that is was a call to Object.wait(. ) or something like that. Check the javadoc for the offending method to find out what circumstances cause the exception to be thrown.
(And once you are done, remember to move the try / catch block you added.)
Resolving IllegalMonitorStateException In Java
In this tutorial, we will learn IllegalMonitorStateException and when it is thrown with examples. We will also see how we can prevent our code from throwing this exception along with some of the best practices to follow in multithreaded applications.
1. Java IllegalMonitorStateException class
IllegalMonitorStateException class present in java.lang package and has been there since Java version 1.0. It extends RuntimeException class; hence, it’s an unchecked exception and needs not to be declared in a method’s or a constructor’s throws clause.
Constructors defined in this class:
- IllegalMonitorStateException(): Creates an instance of the IllegalMonitorStateException class, setting null as its message.
- IllegalMonitorStateException(String message): Creates an instance of the IllegalMonitorStateException class, using the specified message.
2. What causes IllegalMonitorStateException
For inter-thread communication (in which 2 threads communicate with each other), threads have to use wait() , notify() and notifyAll() methods. Thread class inherits these methods from the Object class.
A Thread should acquire the object’s lock to call these methods on that object. If a Thread tries to call wait(), notify() and notifyAll() methods on an object without acquiring that object’s lock or outside of the synchronized block, the program throws IllegalMonitorStateException.
Let’s now look at an example of how a Thread raises IllegalMonitorStateException. In this example, we are going to create a Waiting Thread and a Notifying Thread.
- WaitingThread calls the wait() method and enters into a waiting state until some other Thread calls notify() method and notifies it.
- NotifyingThreadcalls the notify() method and notifies the waiting Thread to start processing again.
public class IllegalMonitorStateExceptionDemo < //This object is used for synchronization among threads. public final static Object obj = new Object(); public static class WaitingThread extends Thread < @Override public void run() < try < //Calling wait() method outside of synchronized area obj.wait(); // Raises IllegalMonitorStateException >catch (InterruptedException ex) < System.out.println(Thread.currentThread().getName() + " gets Interrupted"); >> > public static class NotifyingThread extends Thread < @Override public void run() < try < // Thread sleep for 5 sec Thread.sleep(5000); // Calling notify() outside of synchronized area obj.notify(); // Raises IllegalMonitorStateException >catch (InterruptedException ex) < System.err.println(Thread.currentThread().getName() + " gets Interrupted"); >> > >
Try running both threads to verify.
public static void main(String[] args)
We will get the IllegalMonitorStateException in the console.
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread is not owner at java.base/java.lang.Object.wait(Native Method) at java.base/java.lang.Object.wait(Object.java:338) at com.howtodoinjava.concurrency.IllegalMonitorStateExceptionDemo $WaitingThread.run(IllegalMonitorStateExceptionDemo.java:23) Exception in thread "Thread-1" java.lang.IllegalMonitorStateException: current thread is not owner at java.base/java.lang.Object.notify(Native Method) at com.howtodoinjava.concurrency.IllegalMonitorStateExceptionDemo $NotifyingThread.run(IllegalMonitorStateExceptionDemo.java:39)
3. Resolving IllegalMonitorStateException
IllegalMonitorStateException resolves when a Thread calls wait() , notify() and notifyAll() methods on an object after acquiring that object’s lock means it should call these methods inside synchronized block only.
In the above example, if both Waiting & Notifying Threads call wait() and notify() in synchronized block then we won’t get IllegalMonitorStateException in our code.
So the correct way of calling these methods without this exception is as below,
public static class WaitingThread extends Thread < @Override public void run() < try < //Obtain lock using the synchronized keyword synchronized(obj)< //Calling wait() inside synchronized block obj.wait(); >> catch (InterruptedException ex) < System.err.println(Thread.currentThread().getName() + " gets Interrupted"); >> > public static class NotifyingThread extends Thread < @Override public void run() < try < Thread.sleep(5000); //Obtain lock first synchronized(obj)< //Calling notify() inside synchronized block obj.notify(); >> catch (InterruptedException ex) < System.err.println(Thread.currentThread().getName() + " gets Interrupted"); >> >
Now if we run the program, it completes successfully.
- Since Java version 1.5, we have java.util.concurrent package which contains various new concurrency classes and frameworks that make our work easy while working in a multithreaded environment.
- For inter-thread communication, instead of using the old way of using wait() and notify() method, we can make use of BlockingQueue instead present in java.util.concurrent package.
- BlockingQueue Interface represents a queue that is thread-safe to put into and take elements from while 2 Threads are communicating with each other, which in turn avoids any IllegalMonitorStateException as well.
- Lock Interface and ReentrantLockclass provide more control over the concurrency as compared with synchronized block. Using it, a Thread can try for a lock without waiting, eliminating the chances of a deadlocksituation.
- We can use other classes like CountDownLatch, CyclicBarrier, Exchanger, Phaser, SynchronousQueue in order to work with multiple threads in a multithreaded application.
In this article, we learned about IllegalMonitorStateException, what are the causes for this and how to prevent it in our code. We have also seen some of the best practices for using new concurrency classes that can help in avoiding the IllegalMonitorStateException.
How to Handle the Illegal Monitor State Exception in Java
An IllegalMonitorStateException is a runtime exception in Java that occurs in multithreaded applications. It indicates that the calling thread has attempted to wait on an object’s monitor, or attempted to notify other threads waiting on an object’s monitor, without owning the specified monitor.
Since the IllegalMonitorStateException is an unchecked exception, it does not need to be declared in the throws clause of a method or constructor.
What Causes IllegalMonitorStateException
When building multithreaded applications in Java, if a monitor needs to be synchronized on, the IllegalMonitorStateException is thrown to indicate a thread attempted to wait or to notify other threads waiting on that monitor, without owning it.
Therefore, this exception occurs if one of the wait() , notify() or notifyAll() methods of the Object class are called outside a synchronized block or method.
IllegalMonitorStateException Example
Here’s an example of an IllegalMonitorStateException , thrown when the wait() method is called outside a synchronized block:
class MyRunnable implements Runnable < public void run() < try < this.wait(100); // calling wait() without outside synchronized block System.out.println("Thread in runnable state"); >catch (InterruptedException e) < e.printStackTrace(); >> > public class IllegalMonitorStateExceptionExample < public static void main(String[] args) < MyRunnable myRunnable = new MyRunnable(); Thread myThread = new Thread(myRunnable); myThread.start(); >>
Since a thread must own a lock on the object’s monitor before calling the wait() method, calling it outside a synchronized block throws an IllegalMonitorStateException. Running the above code throws the exception:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread is not owner at java.base/java.lang.Object.wait(Native Method) at java.base/java.lang.Object.wait(Object.java:321) at MyRunnable.run(IllegalMonitorStateExceptionExample.java:4) at java.base/java.lang.Thread.run(Thread.java:832)
How to Resolve IllegalMonitorStateException
The IllegalMonitorStateException can be resolved by calling the wait() , notify() and notifyAll() methods after acquiring an object lock, i.e. within a synchronized block or method.
The call to the wait() method in the earlier example can be placed inside a synchronized block to resolve the exception:
class MyRunnable implements Runnable < public void run() < synchronized (this) < try < this.wait(100); System.out.println("Thread in runnable state"); >catch (InterruptedException e) < e.printStackTrace(); >> > > public class IllegalMonitorStateExceptionExample < public static void main(String[] args) < MyRunnable myRunnable = new MyRunnable(); Thread myThread = new Thread(myRunnable); myThread.start(); >>
Calling the wait() method within a synchronized block helps acquire a lock on the object monitor, which fixes the issue. Running the above code produces the correct output as expected:
Track, Analyze and Manage Errors With Rollbar
Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!