我很难理解我从jstack获得的在Tomcat 6(java 1.6.0_22,Linux)上运行的Spring MVC Web应用程序的线程转储。
我看到阻塞线程(导致其他线程等待)自己被阻塞,但是线程转储没有告诉我为什么或者他们正在等待哪个监视器。
示例:
"TP-Processor75" daemon prio=10 tid=0x00007f3e88448800 nid=0x56f5 waiting for monitor entry [0x00000000472bc000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Class.initAnnotationsIfNecessary(Class.java:3067)
- locked <0x00007f3e9a0b3830> (a java.lang.Class for org.catapultframework.resource.ResourceObject)
at java.lang.Class.getAnnotation(Class.java:3029)
...
即。我错过了堆栈跟踪中的“等待锁定...”行。显然线程锁定了一个Class对象,但是我不明白为什么线程本身被阻塞了。
线程转储不包含任何死锁提示。
如何识别锁定监视器?
谢谢, 奥利弗
答案 0 :(得分:10)
显然,我们观察到这些被阻塞的线程的情况与大量内存消耗和大量垃圾收集有关。
这个问题Java blocking issue: Why would JVM block threads in many different classes/methods?描述了类似的情况,所以我相信这些线程只是被垃圾收集器阻止了。
(无论如何,解决了内存问题后,阻塞线程的这个问题就消失了。)
答案 1 :(得分:5)
检查终结器线程是否被阻止或等待。
在GC扫描期间,GC将“停止世界”#34;执行清理。 &#34;世界&#34;的定义取决于正在使用的垃圾收集器和上下文。它可能是一小组线程或所有线程。在正式收集垃圾之前,GC将调用该对象的finalize()。
如果您处于实施终结器方法的不良情况,最终确定代码可能会阻止它完成和“世界”。停止了。
当看到许多线程被一些未知的魔法力量永久阻挡时,这是最明显的:查找阻塞发生的代码并且没有任何意义;在它附近的任何地方都没有阻塞代码,并且转储不会泄露它正在等待的监视器,因为它没有。 GC暂停了线程。
答案 2 :(得分:2)
我刚刚在谷歌浏览器中使用Applet时遇到了类似的问题。
简而言之:
详细信息:
我有以下情况:
Executor
的{{1}}来分离调用,以减少等待时间,从而在JS中挂起。说明:
new Runnable() ...
是一个匿名内部类,在JS调用发生之前未加载。以下是尝试加载类的被阻止线程:
new Runnable()
正如您所看到的,它正在等待消息 - &gt; "Thread-20" daemon prio=4 tid=0x052e8400 nid=0x4608 in Object.wait() [0x0975d000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at sun.plugin2.message.Queue.waitForMessage(Unknown Source)
- locked <0x29fbc5d8> (a sun.plugin2.message.Queue)
at sun.plugin2.message.Pipe$2.run(Unknown Source)
at com.sun.deploy.util.Waiter$1.wait(Unknown Source)
at com.sun.deploy.util.Waiter.runAndWait(Unknown Source)
at sun.plugin2.message.Pipe.receive(Unknown Source)
at sun.plugin2.main.client.MessagePassingExecutionContext.doCookieOp(Unknown Source)
at sun.plugin2.main.client.MessagePassingExecutionContext.getCookie(Unknown Source)
at sun.plugin2.main.client.PluginCookieSelector.getCookieFromBrowser(Unknown Source)
at com.sun.deploy.net.cookie.DeployCookieSelector.getCookieInfo(Unknown Source)
at com.sun.deploy.net.cookie.DeployCookieSelector.get(Unknown Source)
- locked <0x298da868> (a sun.plugin2.main.client.PluginCookieSelector)
at sun.net.www.protocol.http.HttpURLConnection.setCookieHeader(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.writeRequests(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
- locked <0x2457cdc0> (a sun.net.www.protocol.http.HttpURLConnection)
at com.sun.deploy.net.HttpUtils.followRedirects(Unknown Source)
at com.sun.deploy.net.BasicHttpRequest.doRequest(Unknown Source)
at com.sun.deploy.net.BasicHttpRequest.doGetRequestEX(Unknown Source)
at com.sun.deploy.cache.ResourceProviderImpl.checkUpdateAvailable(Unknown Source)
at com.sun.deploy.cache.ResourceProviderImpl.isUpdateAvailable(Unknown Source)
at com.sun.deploy.cache.DeployCacheHandler.get(Unknown Source)
- locked <0x245727a0> (a java.lang.Object)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
- locked <0x24572020> (a sun.net.www.protocol.http.HttpURLConnection)
at java.net.HttpURLConnection.getResponseCode(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader.getBytes(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader.access$000(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
- locked <0x299726b8> (a sun.plugin2.applet.Applet2ClassLoader)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
- locked <0x299726b8> (a sun.plugin2.applet.Applet2ClassLoader)
at java.lang.ClassLoader.loadClass(Unknown Source)
。
与此同时,我们传入的JS调用在此处被阻止:
waitForMessage()
以相同方式阻止其他其他线程。我想所有后续的类加载请求都被第一个被阻止的类加载线程阻塞。
如前所述,我的猜测是,挂起的JS调用阻止了类加载过程,该调用本身被要加载的缺失类阻塞。
解决方案:
我对#3的实施:
"Applet 1 LiveConnect Worker Thread" prio=4 tid=0x05231800 nid=0x1278 waiting for monitor entry [0x0770e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at MyClass.myMethod(MyClass.java:23)
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.Trampoline.invoke(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.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$PerAppletInfo$LiveConnectWorker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
答案 3 :(得分:1)
这是Oracle的HotSpot JVM中的一个装饰性错误 - 在您的堆栈跟踪中,您会看到- locked <0x00007f3e9a0b3830>
实际应该说- waiting to lock <0x00007f3e9a0b3830>
。
有关详细信息,请参阅this bug。