2017-07-28 45 views
3

我已经复制了一个可疑的线程转储。我在调用java.net.SocketInputStream.socketRead0() 时看到IN_NATIVE状态的173个线程,在同一个调用中有30个线程处于BLOCKED状态。
我认为BLOCKED状态不会消耗CPU,但他们正在等待IO。Java线程转储CPU或只是IO等待?

IN_NATIVE状态的线程怎么样?他们消耗CPU吗? 任何想法,为什么我看到相同的调用socketRead0()不同的线程状态?

173 threads 
Thread 40283 - threadId:Thread 40283 - state:IN_NATIVE 
stackTrace: 
java.net.SocketInputStream.socketRead0(java.io.FileDescriptor, byte[], int, int, int) @bci=0 (Compiled frame; information may be imprecise) 
java.net.SocketInputStream.read(byte[], int, int, int) @bci=87, line=152 (Compiled frame) 
java.net.SocketInputStream.read(byte[], int, int) @bci=11, line=122 (Compiled frame) 
com.sun.mail.util.TraceInputStream.read(byte[], int, int) @bci=7, line=110 (Compiled frame) 
java.io.BufferedInputStream.fill() @bci=175, line=235 (Compiled frame) 
java.io.BufferedInputStream.read() @bci=12, line=254 (Compiled frame) 
com.sun.mail.util.LineInputStream.readLine() @bci=33, line=88 (Compiled frame) 
com.sun.mail.smtp.SMTPTransport.readServerResponse() @bci=43, line=1589 (Compiled frame) 
com.sun.mail.smtp.SMTPTransport.openServer(java.lang.String, int) @bci=117, line=1369 (Compiled frame) 
com.sun.mail.smtp.SMTPTransport.protocolConnect(java.lang.String, int, java.lang.String, java.lang.String) @bci=270, line=412 (Compiled frame) 
javax.mail.Service.connect(java.lang.String, int, java.lang.String, java.lang.String) @bci=380, line=288 (Compiled frame) 
com.healthies.push.injectors.mailsenders.DefaultMailSender.sendMessage(com.healthies.push.messages.EmailMessage, javax.mail.internet.MimeMessage) @bci=28, line=63 (Compiled frame) 
com.healthies.push.injectors.SMTPMessageInjector.sendMessage(com.healthies.push.injectors.mailsenders.MailSender, com.healthies.push.messages.EmailMessage, javax.mail.internet.MimeMessage) @bci=55, line=140 (Compiled frame) 
com.healthies.push.injectors.SMTPMessageInjector.inject(com.healthies.push.messages.EmailMessage) @bci=210, line=117 (Compiled frame) 
com.healthies.push.injectors.SMTPMessageInjector.inject(com.healthies.push.messages.Message) @bci=5, line=35 (Compiled frame) 
com.healthies.push.injectors.EmailInjectorPool$1.run() @bci=85, line=40 (Compiled frame) 
java.util.concurrent.Executors$RunnableAdapter.call() @bci=4, line=471 (Compiled frame) 
java.util.concurrent.FutureTask.run() @bci=42, line=262 (Compiled frame) 
java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95, line=1145 (Compiled frame) 
java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=615 (Interpreted frame) 
java.lang.Thread.run() @bci=11, line=745 (Interpreted frame) 
-------------------------------------------------------------------- 
30 threads 
Thread 40276 - threadId:Thread 40276 - state:BLOCKED 
stackTrace: 
java.net.SocketInputStream.socketRead0(java.io.FileDescriptor, byte[], int, int, int) @bci=0 (Compiled frame; information may be imprecise) 
java.net.SocketInputStream.read(byte[], int, int, int) @bci=87, line=152 (Compiled frame) 
java.net.SocketInputStream.read(byte[], int, int) @bci=11, line=122 (Compiled frame) 
com.sun.mail.util.TraceInputStream.read(byte[], int, int) @bci=7, line=110 (Compiled frame) 
java.io.BufferedInputStream.fill() @bci=175, line=235 (Compiled frame) 
java.io.BufferedInputStream.read() @bci=12, line=254 (Compiled frame) 
com.sun.mail.util.LineInputStream.readLine() @bci=33, line=88 (Compiled frame) 
com.sun.mail.smtp.SMTPTransport.readServerResponse() @bci=43, line=1589 (Compiled frame) 
com.sun.mail.smtp.SMTPTransport.issueSendCommand(java.lang.String, int) @bci=6, line=1494 (Compiled frame) 
com.sun.mail.smtp.SMTPTransport.finishData() @bci=34, line=1321 (Compiled frame) 
com.sun.mail.smtp.SMTPTransport.sendMessage(javax.mail.Message, javax.mail.Address[]) @bci=281, line=637 (Compiled frame) 
com.healthies.push.injectors.mailsenders.DefaultMailSender.sendMessage(com.healthies.push.messages.EmailMessage, javax.mail.internet.MimeMessage) @bci=37, line=64 (Compiled frame) 
com.healthies.push.injectors.SMTPMessageInjector.sendMessage(com.healthies.push.injectors.mailsenders.MailSender, com.healthies.push.messages.EmailMessage, javax.mail.internet.MimeMessage) @bci=55, line=140 (Compiled frame) 
com.healthies.push.injectors.SMTPMessageInjector.inject(com.healthies.push.messages.EmailMessage) @bci=210, line=117 (Compiled frame) 
com.healthies.push.injectors.SMTPMessageInjector.inject(com.healthies.push.messages.Message) @bci=5, line=35 (Compiled frame) 
com.healthies.push.injectors.EmailInjectorPool$1.run() @bci=85, line=40 (Compiled frame) 
java.util.concurrent.Executors$RunnableAdapter.call() @bci=4, line=471 (Compiled frame) 
java.util.concurrent.FutureTask.run() @bci=42, line=262 (Compiled frame) 
java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95, line=1145 (Compiled frame) 
java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=615 (Interpreted frame) 
java.lang.Thread.run() @bci=11, line=745 (Interpreted frame) 
+0

套接字读取可以通过旋转(在非阻塞模式下并且无所事事)来消耗CPU时间或者阻塞线程,jstack不会告诉你它是哪一个。 – the8472

回答

1

正常情况下,您永远不会看到一个线程在BLOCKED状态下执行非同步本机方法。但是这个转储是在强制模式下获得的(jstack -F),其中works differently

看起来JVM已经要求safepoint operation。运行Java代码的所有线程都必须在安全点处停止,但本地方法仍可以运行。只要本机方法返回,它就会检查是否正在执行safepoint操作,如果是,则会阻止当前线程,直到VM操作完成。

所以,你的情况

  • 线程BLOCKED状态已经完成了本地通话,正在等待从该方法返回的还原点运转结束;
  • 线程在IN_NATIVE状态仍在执行本机呼叫,其中可能被阻塞在套接字读取上。

JVM没有手段来区分阻塞从天然方法实际上消耗CPU系统调用本机方法 - 在两种情况下,它会显示一个线程在IN_NATIVE状态。你不能从线程转储得出这些线程是否忙。

为了看本地方法是否消耗CPU,您将需要一个实用程序,如top,perfnative code aware profiler