The JVM only keeps track of the local thread that has the monitor, if the calling class makes an external call back in on itself the incoming call causes the original thread to deadlock itself.
You should be able to run this code to illustrate the idea
import java.rmi.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.*;
public class DeadlockThreadExample {
public static interface DeadlockClass extends Remote {
public void execute() throws RemoteException;
}
public static class DeadlockClassImpl extends UnicastRemoteObject implements DeadlockClass {
private Object lock = new Object();
public DeadlockClassImpl() throws RemoteException {
super();
}
public void execute() throws RemoteException {
try {
System.out.println("execute()::start");
synchronized (lock) {
System.out.println("execute()::Entered Lock");
DeadlockClass deadlockClass = (DeadlockClass) Naming.lookup("rmi://localhost/DeadlockClass");
deadlockClass.execute();
}
System.out.println("execute()::Exited Lock");
} catch (NotBoundException e) {
System.out.println(e.getMessage());
} catch (java.net.MalformedURLException e) {
System.out.println(e.getMessage());
}
System.out.println("execute()::end");
}
}
public static void main(String[] args) throws Exception {
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
DeadlockClassImpl deadlockClassImpl = new DeadlockClassImpl();
Naming.rebind("DeadlockClass", deadlockClassImpl);
DeadlockClass deadlockClass = (DeadlockClass) Naming.lookup("rmi://localhost/DeadlockClass");
deadlockClass.execute();
System.exit(0);
}
}
The output from the program looks like
execute()::start
execute()::Entered Lock
execute()::start
Additionally the thread also dump shows the following
"main" prio=6 tid=0x00037fb8 nid=0xb80 runnable [0x0007f000..0x0007fc3c]
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:235)
- locked <0x02fdc568> (a java.io.BufferedInputStream)
at java.io.DataInputStream.readByte(DataInputStream.java:241)
"RMI TCP Connection(4)-172.17.23.165" daemon prio=6 tid=0x0ad83d30 nid=0x1590 waiting for monitor entry [0x0b3cf000..0x0b3cfce8]
at DeadlockThreadExample$DeadlockClassImpl.execute(DeadlockThreadExample.java:24)
- waiting to lock <0x0300a848> (a java.lang.Object)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
"RMI TCP Connection(2)-172.17.23.165" daemon prio=6 tid=0x0ad74008 nid=0x15f0 runnable [0x0b24f000..0x0b24fbe8]
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:235)
- locked <0x02ffb6d8> (a java.io.BufferedInputStream)
at java.io.DataInputStream.readByte(DataInputStream.java:241)
which indicates that the thread has indeed managed to lock itself