2017-07-28 54 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