I am having trouble avoiding a sporadic crash in my applet that appears to be caused by a thread waiting on itself. Strangely, this only seems to happen in google chrome.
30-second read:
- Applet.methodA() calls JSObject.javascriptMethod()
- javascriptMethod() makes a Applet.methodB() call
- Applet.methodB() waits for Applet.methodA() to release its lock, which never happens..
What I've Tried:
- using setTimeout in javascriptMethod. no luck there.
- using JSObject.eval() instead of JSObject.call()
Also possible: that i've t开发者_高级运维otally misinterpreted the thread dump. Here it is for inspection.
My understanding:
- The sequencer thread calls applet.notifyPosition
- notifyPosition calls a javascript method
- javascript method calls applet.pause
applet.pause needs to lock the sequencer, but can't because it's busy calling notifyposition..
"Java Sound Sequencer" prio=8 tid=0x189de400 nid=0x86c in Object.wait() [0x1c6ae000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x099c50e0> (a java.lang.Object) at com.sun.media.sound.RealTimeSequencer$PlayThread.stop(Unknown Source) - locked <0x099c50e0> (a java.lang.Object) - locked <0x099c50e8> (a com.sun.media.sound.RealTimeSequencer$PlayThread) at com.sun.media.sound.RealTimeSequencer.implStop(Unknown Source) at com.sun.media.sound.RealTimeSequencer.stop(Unknown Source) - locked <0x099c8ca8> (a com.sun.media.sound.RealTimeSequencer) at net.alphatab.midi.MidiPlayer.pause(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at sun.plugin.javascript.JSInvoke.invoke(Unknown Source) at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at sun.plugin.javascript.JSClassLoader.invoke(Unknown Source) at sun.plugin2.liveconnect.JavaClass$MethodInfo.invoke(Unknown Source) at sun.plugin2.liveconnect.JavaClass$MemberBundle.invoke(Unknown Source) at sun.plugin2.liveconnect.JavaClass.invoke0(Unknown Source) at sun.plugin2.liveconnect.JavaClass.invoke(Unknown Source) at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$DefaultInvocationDelegate.invoke(Unknown Source) at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo.doObjectOp(Unknown Source) at sun.plugin2.main.client.LiveConnectSupport.doObjectOp(Unknown Source) at sun.plugin2.main.client.MessagePassingJSObject.waitForReply(Unknown Source) at sun.plugin2.main.client.MessagePassingJSObject.call(Unknown Source) at net.alphatab.midi.MidiPlayer.notifyPosition(Unknown Source) at net.alphatab.midi.MidiPlayer.access$200(Unknown Source) at net.alphatab.midi.MidiPlayer$1.controlChange(Unknown Source) at net.alphatab.midi.TickNotifierReceiver.send(Unknown Source) at com.sun.media.sound.AbstractMidiDevice$TransmitterList.sendMessage(Unknown Source) - locked <0x0982d8e8> (a java.util.ArrayList) at com.sun.media.sound.RealTimeSequencer$DataPump.dispatchMessage(Unknown Source) at com.sun.media.sound.RealTimeSequencer$DataPump.pump(Unknown Source) - locked <0x09a56ae8> (a com.sun.media.sound.RealTimeSequencer$DataPump) at com.sun.media.sound.RealTimeSequencer$PlayThread.run(Unknown Source) at java.lang.Thread.run(Unknown Source)
Here we see the part that looks like a problem:
"Java Sound Sequencer" prio=8 tid=0x189de400 nid=0x86c in Object.wait() [0x1c6ae000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x099c50e0> (a java.lang.Object)
at com.sun.media.sound.RealTimeSequencer$PlayThread.stop(Unknown Source)
- locked <0x099c50e0> (a java.lang.Object)
This waiting on <0x099c50e0>
does not mean that the thread waits to get the lock, but it had the lock, and called wait()
on this object, meaning that it temporarily gave the lock away and waits until some other thread will call .notify()
or .notifyAll()
on this same object.
Thus, this single stack trace does not show a deadlock.
Of course, it could be that the actual calls from applet to JavaScript and from JavaScript back to applet are on different threads, which could show the behavior you describe. But the stack trace you have here does not seem to indicate this (I suppose the alphatab classes are your's).
The problem is simply that nobody is calling notify()
for some reason. Maybe there was some synchronization error, so the notify actually came before the wait. Or some other thread is waiting on some other lock before notifying (this would be a real dead lock).
精彩评论