[kaffe] Unexpected java.lang.IllegalMonitorStateException
Ito Kazumitsu
ito.kazumitsu@hitachi-cable.co.jp
Wed Mar 24 05:37:03 2004
In message "[kaffe] java.io.ObjectInputStream: final field cannot be restored"
on 04/03/24, Ito Kazumitsu <ito.kazumitsu@hitachi-cable.co.jp> writes:
> Interested in Prevayler (http://www.prevayler.org/), which is
> marked untested in our "Compatibility - Application Testing",
> I tried it.
>
> The result was unsatisfactory. The simplest demo of Prevayler
> cannot run on kaffe. After studying the cause of the error,
> I found something buggy in java.io.ObjectInputStream.
There is another problem about running Prevayler.
The behavior of the attached program when run on kaffe is
different from the behavior when run on Sun's JDK.
Kaffe:
bash$ java TestSync
sync(): thread=Thread[Thread-1,5,main]
sync(): This is TestSync$SyncBatch@8248714
sync(): waiting
setSynched(): thread=Thread[Thread-2,5,main]
setSynched(): This is TestSync$SyncBatch@8248714
(Waits endlessly)
^C
or
bash$ java TestSync
sync(): thread=Thread[Thread-1,5,main]
sync(): This is TestSync$SyncBatch@8248714
sync(): waiting
setSynched(): thread=Thread[Thread-2,5,main]
setSynched(): This is TestSync$SyncBatch@8248714
java.lang.IllegalMonitorStateException
at TestSync$SyncBatch.setSynched (TestSync.java:47)
at TestSync$Thread2.run (TestSync.java:26)
Sun's JDK:
bash$ java TestSync
sync(): thread=Thread[Thread-0,5,main]
sync(): This is TestSync$SyncBatch@1ac04e8
sync(): waiting
setSynched(): thread=Thread[Thread-1,5,main]
setSynched(): This is TestSync$SyncBatch@1ac04e8
bash$
(Ends normally)
Problem about Kaffe's behavior:
"sync(): waiting" means that Thread1 has unlocked the object
on which to wait. So Thread2 can obtain the lock and run
setSynched(). Then Thread2 must have become the owner of
the object's monitor and it can execute notifyAll() without
problem. So the program should end normally. Kaffe's
behaviors (endless waiting or IllegalMonitorStateException)
seem buggy.
Test Program:
public class TestSync {
public static void main(String[] args) throws Exception {
SyncBatch sb = (new TestSync()).new SyncBatch();
new Thread1(sb).start();
Thread.sleep(2000);
new Thread2(sb).start();
}
private static class Thread1 extends Thread {
private SyncBatch _sb;
public Thread1(SyncBatch sb) {
_sb = sb;
}
public void run() {
_sb.sync();
}
}
private static class Thread2 extends Thread {
private SyncBatch _sb;
public Thread2(SyncBatch sb) {
_sb = sb;
}
public void run() {
_sb.setSynched();
}
}
private class SyncBatch {
synchronized void sync() {
System.err.println("sync(): thread=" + Thread.currentThread());
System.err.println("sync(): This is " + this);
try {
System.err.println("sync(): waiting");
this.wait();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
synchronized void setSynched() {
System.err.println("setSynched(): thread=" + Thread.currentThread());
System.err.println("setSynched(): This is " + this);
synchronized (this) { notifyAll(); }
}
}
}