如何将 java 与 javascript 调用解耦?小程序正在等待自己!
我无法避免小程序中的偶发崩溃,这似乎是由线程等待自身引起的。奇怪的是,这似乎只发生在谷歌浏览器中。
30 秒读取:
- Applet.methodA() 调用 JSObject.javascriptMethod()
- javascriptMethod() 进行 Applet.methodB() 调用
- Applet.methodB() 等待 Applet.methodA() 释放其锁定,这永远不会发生。
我尝试过的:
- 在 javascriptMethod 中使用 setTimeout。那里没有运气。
- 使用 JSObject.eval() 而不是 JSObject.call()
也可以: 我完全误解了线程转储。这里是供检查用的。
我的理解:
- sequencer线程调用applet.notifyPosition
- notifyPosition调用javascript方法
- javascript方法调用applet.pause
applet.pause需要锁定sequencer,但不能,因为它正忙于调用notifyposition..
Object.wait() 中的“Java 声音音序器”prio=8 tid=0x189de400 nid=0x86c [0x1c6ae000] java.lang.Thread.State:TIMED_WAITING(在对象监视器上) 在 java.lang.Object.wait(本机方法) - 等待<0x099c50e0> (一个java.lang.Object) 在 com.sun.media.sound.RealTimeSequencer$PlayThread.stop(来源未知) - 锁定<0x099c50e0> (一个java.lang.Object) - 锁定<0x099c50e8> (com.sun.media.sound.RealTimeSequencer$PlayThread) 在 com.sun.media.sound.RealTimeSequencer.implStop(来源未知) 在 com.sun.media.sound.RealTimeSequencer.stop(来源未知) - 锁定<0x099c8ca8> (com.sun.media.sound.RealTimeSequencer) 在 net.alphatab.midi.MidiPlayer.pause(来源未知) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法) 在 sun.reflect.NativeMethodAccessorImpl.invoke(来源未知) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(来源未知) 在 java.lang.reflect.Method.invoke(来源未知) 在 sun.plugin.javascript.JSInvoke.invoke(来源未知) 在 sun.reflect.GenerateMethodAccessor3.invoke(来源未知) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(来源未知) 在 java.lang.reflect.Method.invoke(来源未知) 在 sun.plugin.javascript.JSClassLoader.invoke(来源未知) 在 sun.plugin2.liveconnect.JavaClass$MethodInfo.invoke(来源未知) 在 sun.plugin2.liveconnect.JavaClass$MemberBundle.invoke(来源未知) 在 sun.plugin2.liveconnect.JavaClass.invoke0(来源未知) 在 sun.plugin2.liveconnect.JavaClass.invoke(来源未知) 在 sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$DefaultInitationDelegate.invoke(来源未知) 在 sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$3.run(来源未知) 在 java.security.AccessController.doPrivileged(本机方法) 在 sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo.doObjectOp(来源未知) 在 sun.plugin2.main.client.LiveConnectSupport.doObjectOp(来源未知) 在 sun.plugin2.main.client.MessagePassingJSObject.waitForReply(来源未知) 在 sun.plugin2.main.client.MessagePassingJSObject.call(来源未知) 在 net.alphatab.midi.MidiPlayer.notifyPosition(来源未知) 在 net.alphatab.midi.MidiPlayer.access$200(来源不明) 在 net.alphatab.midi.MidiPlayer$1.controlChange(来源不明) 在 net.alphatab.midi.TickNotifierReceiver.send(来源未知) 在 com.sun.media.sound.AbstractMidiDevice$TransmitterList.sendMessage(来源未知) - 锁定<0x0982d8e8> (一个java.util.ArrayList) 在 com.sun.media.sound.RealTimeSequencer$DataPump.dispatchMessage(来源未知) 在 com.sun.media.sound.RealTimeSequencer$DataPump.pump(来源未知) - 锁定<0x09a56ae8> (com.sun.media.sound.RealTimeSequencer$DataPump) 在 com.sun.media.sound.RealTimeSequencer$PlayThread.run(来源未知) 在 java.lang.Thread.run(来源未知)
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 totally 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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里我们看到了看起来有问题的部分:
这个等待
<0x099c50e0>
并不意味着线程等待获取锁,而是它拥有锁,并在此对象上调用wait()
,这意味着它暂时放弃锁并等待,直到其他线程调用.notify()
或在同一对象上的.notifyAll()
。因此,这个单一堆栈跟踪不会显示死锁。
当然,从 applet 到 JavaScript 以及从 JavaScript 返回到 applet 的实际调用可能位于不同的线程上,这可能会显示您所描述的行为。但你在这里的堆栈跟踪似乎并没有表明这一点(我想 alphatab 类是你的)。
问题很简单,就是没有人出于某种原因调用
notify()
。也许存在一些同步错误,所以通知实际上是在等待之前发生的。或者其他一些线程在通知之前正在等待其他锁(这将是真正的死锁)。Here we see the part that looks like a problem:
This waiting on
<0x099c50e0>
does not mean that the thread waits to get the lock, but it had the lock, and calledwait()
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).