jstack 显示的线程是出问题的线程还是所有的线程?

2017-11-15 19:04:52 +08:00
 esolve

如果是所有的线程

那对于正常的线程来说

那那些 at 代表啥?

如果是出问题的线程

有的线程状态是 running,有啥问题?

1456 次点击
所在节点    问与答
8 条回复
kaneg
2017-11-15 20:28:32 +08:00
所有的。
at 是每个线程当前正在执行方法的堆栈信息
esolve
2017-11-15 23:16:30 +08:00
@kaneg 一个线程里面的代码分支很多,at 只是其中的一条,为何只显示其中一条?是这条出问题了吗?
kaneg
2017-11-16 07:06:25 +08:00
@esolve 是 jstack 运行的那个时候,线程执行到的那个分支
esolve
2017-11-16 11:10:57 +08:00
@kaneg 那如何定位问题啊

譬如一个 http 线程耗时很长甚至不成功,
要排查原因
那怎么找到问题?


假设线程有好几个数据库查询语句,
有一个语句耗时很长甚至不成功
我想找到这个语句

你的意思 jstack 是快照,
那么我用 jstack 的时候,这个线程恰好运行到没啥问题的其他几个数据库查询
而不是我要找的那个数据库查询
这样怎么找问题所在?
kaneg
2017-11-16 11:28:18 +08:00
@esolve

这种动态的情况用快照这种方法就不一定管用了。一般来说就是打 log,在可能执行到的地方都打上 log,与耗时相关的打上时间,然后在 log 中定位你认为有问题的行,这样逐渐缩小范围,定位到可能出问题的代码行,然后再用 Remote Debug,打好合适的断点,逐行排除,直至找到问题原因。
esolve
2017-11-16 13:23:35 +08:00
@kaneg 有点奇怪,只能快照的话,感觉 jstack 根本找不出问题啊,除非是线程长时间的阻塞。

BTW: 我看到的一个问题是:

java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:100)
at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:143)
at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:173)
- locked <0x000000056ce28410> (a com.mysql.jdbc.util.ReadAheadInputStream)
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2911)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3337)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3327)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2530)
- locked <0x000000056ca3a818> (a com.mysql.jdbc.JDBC4Connection)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1907)
- locked <0x000000056ca3a818> (a com.mysql.jdbc.JDBC4Connection)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2030)
- locked <0x000000056ca3a818> (a com.mysql.jdbc.JDBC4Connection)

这里有几个 locked
这是啥意思? 过程中阻塞了四次?每次一定秒数?
kaneg
2017-11-16 15:15:15 +08:00
@esolve
这里的 locked 是同步锁,在 java 的多线程代码中很常见,没有什么不正常的。
从下面的行可以看出
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)

你的代码在进行持续的 Read 操作,而从下面的 Sql connection 可以推断出,当前线程在执行完一个 sql 后在往回读 Result。

如果这个时间很长,一般有两种原因:

1. 网络速度慢
2. sql 执行后的结果数据量很大
esolve
2017-11-16 18:31:28 +08:00
@kaneg 这上面这些 at 和抛异常的 at 有啥区别
异常里的每一个 at 都是一个函数调用入口,一步一步直到抛出异常的那行
这里的每个 at 代表啥?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/406696

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX