安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

原来jdk自带了这么好玩的工具使用jstack定位死循环

7月19日 发如雪投稿
  什么是jstackjstack的主要作用是查看或者导出java线程的堆栈信息(快照);用于堆栈跟踪,当我们使用jstack命令时,它会将指定进程内的所有线程中方法的调用栈打印出来。
  线程快照是java虚拟机内每一个线程正在执行的方法堆栈的集合,生成线程快照的主要目的是用于定位线程出现问题的位置;常见的问题有响应时间长线程死锁死循环
  当线程停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道线程的执行过程中在后台做了哪些事,在等待哪些资源造成的卡顿。使用方法
  命令格式jstack〔options〕pidoptions参数说明
  jstack的option参数并不多,真正用到的也就三个,接下来我们一个个介绍一下
  F:当线程挂起(Suspended)时,使用jstacklpid命令是不会打印堆栈信息的,使用F则可以强制输出线程堆栈;但是会停止但
  l:打印的信息除了堆栈外,还会显示锁的附加信息;
  m:同时输出java和CC的堆栈信息;在java的系统类库里面,有很多方法都是native修饰的,这些native修饰的方法你在java层面是看不到源码的,因为这些方法都是CC实现的;状态说明
  在线程的堆栈中,需要特别留意以下几种状态:Deadlock:死锁(重点关注)Waitingoncondition:等待资源(重点关注)Waitingonmonitorentry:等待获取监视器(重点关注)Blocked:阻塞(重点关注)Runnable:执行中Suspended:暂停Object。wait()或TIMEWAITING:对象等待中Parked:停止nooption参数
  不带option参数的命令jstack12771
  打印结果如下。。。。。。忽略其他堆栈信息我们只关注main线程的堆栈main1prio5osprio31tid0x00007fee9101a000nid0x2903runnable〔0x00007000085aa000〕java。lang。Thread。State:RUNNABLEatjava。io。FileInputStream。readBytes(NativeMethod)atjava。io。FileInputStream。read(FileInputStream。java:255)atjava。io。BufferedInputStream。fill(BufferedInputStream。java:246)atjava。io。BufferedInputStream。read(BufferedInputStream。java:265)locked0x000000076ab1ead0(ajava。io。BufferedInputStream)atcom。test。Test。main(Test。java:12)。。。。。。。忽略其他堆栈信息我们只关注main线程的堆栈
  第一行各个单词的解析,main:线程名称。prio:线程优先级tid:指JavaThreadid。nid:指native线程的id〔0x00007000085aa000〕:线程栈起始地址。l打印锁的附加信息
  这里我们使用2个窗口,分别使用以下2个命令来测试第一个窗口执行jstackl12771第二个窗口中执行jstack12771
  通过2个窗口对比可以看到,加了l的命令多打印了锁的信息;
  导出堆栈文件
  一般情况下,如果程序出错了,都不会直接在生产环境的服务器上找错误,这个时候就可以用到一个非常实用的功能,将堆栈快照导出来,然后copy到别的电脑上看,命令如下jstackl2289jstackDump。txt
  执行后,就可以看到文件已经导出来了
  通过cat命令可以看到,里面的内容和我们在命令行输出的内容是一样的
  实战一、找出cpu占用最高的线程(linux系统)
  首先我们准备好一个死循环的线程,在线程内定一个while的死循环,并且给这个线程起个名字为:yexindogn,阿里巴巴的开发规范里面有一个规定,就是每个线程必须起一个名字,起名字就是为了以后程序出问题的时候好找错误;publicstaticvoidmain(String〔〕args)throwsInterruptedException{newThread(newRunnable(){Overridepublicvoidrun(){while(true){System。out。println(112);}}},yexindong)。start();System。out。println(我执行了);}
  接着我们将此代码打成jar包扔到linux服务器上运行,直接输入javajarTest。jar命令即可运行,运行后我们可以看到控制台一直在输出112这个字符,这就代表程序已经在运行了;
  接着在看下CPU的运行情况,使用top命令查看cpu占用情况,排在第一位的是进程号为30328的进程,占用了6。6的这边我使用了2个命令行连到同一台服务器,一个窗口用来运行刚刚的jar包,另一个窗口用来查找错误;
  找线程第一种方式
  知道进程号了,接着就是找线程了,输入以下命令topHp30328
  打印结果如下,这里有一点需要注意,在我们加上Hp指令后,PID展示就是线程的id了,这时候我们看到占用CPU最高的线程id是30365;
  找线程第二种方式
  还有另一种方式,就是使用ps命令来查找线程psmp30328oTHREAD,tid,timesortnk1r
  通过这个命令我们可以看到这边占用最高的线程id也是30365;
  以上的方式我们成功找到了占用cpu高的线程id是30365,但这个id是十进制的,在这里需要先转为16进制,输入命令printfx30365
  计算出对应的16进制为:769d
  当然也可以用其他的计算工具,比如mac系统自带计算器就支持进制之间的转换
  使用jstack分析堆栈快照1、快速查找(推荐使用)
  在命令行输入以下命令,这种方法更加快速,推荐使用jstack12771grepA20769d
  其中,grep命令是查找结果为769d的内容,A20表示打印匹配所在行的后20行内容。直接帮我们定位到所在线程的堆栈,结果如下yexindong8prio5osprio0tid0x00007effd0182000nid0x769drunnable〔0x00007effbea0f000〕java。lang。Thread。State:RUNNABLEatjava。io。FileOutputStream。writeBytes(NativeMethod)atjava。io。FileOutputStream。write(FileOutputStream。java:326)atjava。io。BufferedOutputStream。flushBuffer(BufferedOutputStream。java:82)atjava。io。BufferedOutputStream。flush(BufferedOutputStream。java:140)locked0x00000000ecd6ea10(ajava。io。BufferedOutputStream)atjava。io。PrintStream。write(PrintStream。java:482)locked0x00000000ecd65a10(ajava。io。PrintStream)atsun。nio。cs。StreamEncoder。writeBytes(StreamEncoder。java:221)atsun。nio。cs。StreamEncoder。implFlushBuffer(StreamEncoder。java:291)atsun。nio。cs。StreamEncoder。flushBuffer(StreamEncoder。java:104)locked0x00000000ecd659c8(ajava。io。OutputStreamWriter)atjava。io。OutputStreamWriter。flushBuffer(OutputStreamWriter。java:185)atjava。io。PrintStream。newLine(PrintStream。java:546)locked0x00000000ecd65a10(ajava。io。PrintStream)atjava。io。PrintStream。println(PrintStream。java:737)locked0x00000000ecd65a10(ajava。io。PrintStream)atcom。test。Test1。run(Test。java:13)atjava。lang。Thread。run(Thread。java:748)2、常规方法
  当然也可以用下面的死办法,先打印出所有的堆栈快照;jstack30328
  打印结果如下〔rootVM05centos〕jstack303282021071423:40:34FullthreaddumpOpenJDK64BitServerVM(25。232b09mixedmode):AttachListener10daemonprio9osprio0tid0x00007effa4001000nid0x12f9waitingoncondition〔0x0000000000000000〕java。lang。Thread。State:RUNNABLEDestroyJavaVM9prio5osprio0tid0x00007effd004b800nid0x7679waitingoncondition〔0x0000000000000000〕java。lang。Thread。State:RUNNABLEyexindong8prio5osprio0tid0x00007effd0182000nid0x769drunnable〔0x00007effbea0f000〕java。lang。Thread。State:RUNNABLEatjava。io。FileOutputStream。writeBytes(NativeMethod)atjava。io。FileOutputStream。write(FileOutputStream。java:326)atjava。io。BufferedOutputStream。flushBuffer(BufferedOutputStream。java:82)atjava。io。BufferedOutputStream。flush(BufferedOutputStream。java:140)locked0x00000000ecd6ea10(ajava。io。BufferedOutputStream)atjava。io。PrintStream。write(PrintStream。java:482)locked0x00000000ecd65a10(ajava。io。PrintStream)atsun。nio。cs。StreamEncoder。writeBytes(StreamEncoder。java:221)atsun。nio。cs。StreamEncoder。implFlushBuffer(StreamEncoder。java:291)atsun。nio。cs。StreamEncoder。flushBuffer(StreamEncoder。java:104)locked0x00000000ecd659c8(ajava。io。OutputStreamWriter)atjava。io。OutputStreamWriter。flushBuffer(OutputStreamWriter。java:185)atjava。io。PrintStream。newLine(PrintStream。java:546)locked0x00000000ecd65a10(ajava。io。PrintStream)atjava。io。PrintStream。println(PrintStream。java:737)locked0x00000000ecd65a10(ajava。io。PrintStream)atcom。test。Test1。run(Test。java:13)atjava。lang。Thread。run(Thread。java:748)ServiceThread7daemonprio9osprio0tid0x00007effd013e800nid0x769brunnable〔0x0000000000000000〕java。lang。Thread。State:RUNNABLEC1CompilerThread16daemonprio9osprio0tid0x00007effd013b800nid0x769awaitingoncondition〔0x0000000000000000〕java。lang。Thread。State:RUNNABLEC2CompilerThread05daemonprio9osprio0tid0x00007effd012d000nid0x768bwaitingoncondition〔0x0000000000000000〕java。lang。Thread。State:RUNNABLESignalDispatcher4daemonprio9osprio0tid0x00007effd012a800nid0x7689runnable〔0x0000000000000000〕java。lang。Thread。State:RUNNABLEFinalizer3daemonprio8osprio0tid0x00007effd0101000nid0x7683inObject。wait()〔0x00007effbf906000〕java。lang。Thread。State:WAITING(onobjectmonitor)atjava。lang。Object。wait(NativeMethod)waitingon0x00000000ecd66260(ajava。lang。ref。ReferenceQueueLock)atjava。lang。ref。ReferenceQueue。remove(ReferenceQueue。java:144)locked0x00000000ecd66260(ajava。lang。ref。ReferenceQueueLock)atjava。lang。ref。ReferenceQueue。remove(ReferenceQueue。java:165)atjava。lang。ref。FinalizerFinalizerThread。run(Finalizer。java:216)ReferenceHandler2daemonprio10osprio0tid0x00007effd00fc000nid0x767finObject。wait()〔0x00007effbfa07000〕java。lang。Thread。State:WAITING(onobjectmonitor)atjava。lang。Object。wait(NativeMethod)waitingon0x00000000ecd66418(ajava。lang。ref。ReferenceLock)atjava。lang。Object。wait(Object。java:502)atjava。lang。ref。Reference。tryHandlePending(Reference。java:191)locked0x00000000ecd66418(ajava。lang。ref。ReferenceLock)atjava。lang。ref。ReferenceReferenceHandler。run(Reference。java:153)VMThreadosprio0tid0x00007effd00f2800nid0x767drunnableVMPeriodicTaskThreadosprio0tid0x00007effd0141000nid0x769cwaitingonconditionJNIglobalreferences:5
  接着我用刚刚计算出来的16进制复制出来在这里搜索一下,经过查看就知道是我们刚刚起了名字为yexindong的线程出错了,出错的位置在Test。java的第13行代码
  我们看看java代码,确实是第13行这里的死循环导致的
  实战二、找出cpu占用最高的线程(windows系统)
  首先打开任务管理器,因为默认windows的任务管理器是不显示进程pid的,所以我们需要设置一下,选择查看选择列(S)。。。
  选中PID进程表示符后点击确定按钮
  查进程号pid
  然后我们就可以看到占用CPU最高的java进程PID为:976
  查线程号TID
  因为windows不能直接查看java进程中的线程信息,所以我们需要借助一个工具,这个工具是微软自己开发的,叫做ProcessExplorer,网上很多,需要的童鞋请自行百度,打开后找到pid为976的进程右击选择属性
  在弹出的窗口中找到线程这一栏,它的排序默认就是按照cpu占用的率倒序排列的,所以最上面的就是占用cpu最高的线程了,记住它的线程id:3548
  线程id转16进制
  刚刚拿到的进程id是十进制的,但是我们导出的jstack信息里面,线程id是以16进制来展示的,所以我们要先将这个线程id为3548转为16进制的,使用windows自带的计算器即可,在快捷命令行输入calc
  计算器打开后将其设置为程序员使用的计算器
  接着输入线程id3548,在按一下16进制,就会自动进行转换,结果为ddc,记住这个16进制;
  使用jstack导出堆栈并分析
  在命令行输入以下指令导出进程的堆栈快照信息jstack976jstackInfo。txt
  几秒钟后,快照导出了,静静地躺在文件夹里,等待着我们打开
  用Notepad打开导出的文件,搜索刚刚计算出来的16进制ddc,就可以定位到线程出错的位置了
  在java层面打印堆栈
  有些童鞋可能会觉得用这个jstack命令麻烦了,那java在代码里面可不可以打印出堆栈呢?你别说,还真有,就是这个方法:Thread。getAllStackTraces();光说不练假把式,来个demo测试一下吧publicstaticvoidmain(String〔〕args)throwsInterruptedException{第一个线程,死循环newThread(newRunnable(){Overridepublicvoidrun(){while(true){}}},while)。start();延时一秒Thread。sleep(1000);第二个线程,用来打印堆栈newThread(newRunnable(){Overridepublicvoidrun(){MapThread,StackTraceElement〔〕allStackTracesThread。getAllStackTraces();for(Map。EntryThread,StackTraceElement〔〕threadEntry:allStackTraces。entrySet()){ThreadkeythreadEntry。getKey();System。out。println(key);StackTraceElement〔〕valuethreadEntry。getValue();for(StackTraceElementstackTraceElement:value){System。out。println(stackTraceElement。toString());}}}},stackinfo)。start();}
  执行后打印结果如下,由此可以看到,将当前进程的所有线程都打印出来了,但是这边只打印了简单的堆栈信息,对于开发人员来说,已经起到了监控作用;Thread〔ReferenceHandler,10,system〕java。lang。Object。wait(NativeMethod)java。lang。Object。wait(Object。java:502)java。lang。ref。Reference。tryHandlePending(Reference。java:191)java。lang。ref。ReferenceReferenceHandler。run(Reference。java:153)Thread〔while,5,main〕com。test。Test1。run(Test。java:29)java。lang。Thread。run(Thread。java:748)Thread〔MonitorCtrlBreak,5,main〕java。net。SocketInputStream。socketRead0(NativeMethod)java。net。SocketInputStream。socketRead(SocketInputStream。java:116)java。net。SocketInputStream。read(SocketInputStream。java:171)java。net。SocketInputStream。read(SocketInputStream。java:141)sun。nio。cs。StreamDecoder。readBytes(StreamDecoder。java:284)sun。nio。cs。StreamDecoder。implRead(StreamDecoder。java:326)sun。nio。cs。StreamDecoder。read(StreamDecoder。java:178)java。io。InputStreamReader。read(InputStreamReader。java:184)java。io。BufferedReader。fill(BufferedReader。java:161)java。io。BufferedReader。readLine(BufferedReader。java:324)java。io。BufferedReader。readLine(BufferedReader。java:389)com。intellij。rt。execution。application。AppMainV21。run(AppMainV2。java:61)Thread〔Finalizer,8,system〕java。lang。Object。wait(NativeMethod)java。lang。ref。ReferenceQueue。remove(ReferenceQueue。java:144)java。lang。ref。ReferenceQueue。remove(ReferenceQueue。java:165)java。lang。ref。FinalizerFinalizerThread。run(Finalizer。java:216)Thread〔stackinfo,5,main〕java。lang。Thread。dumpThreads(NativeMethod)java。lang。Thread。getAllStackTraces(Thread。java:1610)com。test。Test2。run(Test。java:39)java。lang。Thread。run(Thread。java:748)Thread〔AttachListener,9,system〕Thread〔SignalDispatcher,9,system〕完
  作为调优和找错的工具来说,可以说jstack是用的最多的一个工具了,但是由于局限性,现在已经慢慢被替换掉了;大家更倾向于使用阿里巴巴开发的工具感兴趣的童鞋可以了解下!
投诉 评论 转载

BOSE发布扬声器850支持杜比全景声内容5月10日,Bose宣布推出全新Bose家庭娱乐扬声器850,不仅外型精巧,更支持杜比全景声内容(DolbyAtmos),为用户带来沉浸动人的聆听与观影体验。通过特有的Bose……HarmonyOS2升级汇总,135款设备已升级正式版,6款从2021年6月份开始,华为正式发布了自主研发的HarmonyOS2系统,这款系统也是首款国产自主研发的成功系统,也是发布之后,升级速度最快,升级人数最多,升级反馈最好的一款手……原来jdk自带了这么好玩的工具使用jstack定位死循环什么是jstackjstack的主要作用是查看或者导出java线程的堆栈信息(快照);用于堆栈跟踪,当我们使用jstack命令时,它会将指定进程内的所有线程中方法的调用栈打印出……企业为什么要上管理系统软件?企业管理和经营作为企业家最重要的日常工作内容,都依赖与准确的市场信息和内部资源信息,这些信息的快速、准确收集,并被在企业经营管理过程更多人员普遍使用,所产生的价值将是我们想不到……使用红米notePro11三个月的感觉用了红米notePro11三个月慢慢发现很不错。本人现在本来有一台水果11和一台vivo,看到了当时红米notePro11铺天盖地的广告,本身喜欢折腾手机的,经过挣扎后首发果断……微信3个功能容易被骗子盯上,要快速查清并清除,老年人也需知道分享生活小妙招,共享科技新生活!大家好,欢迎来到今天的知识分享!我是你们的好朋友小俊!我们在使用微信的同时,其实有3个功能极其容易被骗子盯上并利用,我们一定要快速查清并清……数字化转型的10个关键词文章来源本文作者:阿里研究院副院长安筱鹏博士。正文为2019年安筱鹏博士在清华大学经管学院举办的高教论坛上,围绕数字化转型2。0进行了主题发言,以下是发言主要内容。……上手了丐版MacBookPro之后,我发现它很强,但也有点菜先说结论:明确用途之后再买这台MacBookPro来用,是香的;不明确用途买来,是智商税。磕磕绊绊,在官网预定了半个月之后,托尼终于拿到了这台丐版的14英寸MacBook……你为什么卸载了WPS?我没卸载,而是充了值!知识本来就应该得到尊重。凭什么Office收费再高都没有人说啥,WPS免费提供(无非多点广告)反倒有人唧唧歪歪的?我就充值买了会员,折合下来一个月十块钱都……交通部计划2025年高速公路快速充电覆盖率达809月17日,在2021年世界新能源汽车大会上,交通运输部副部长王志清表示,到2025年中国公交的新能源车比率要达到72,中国高速公路的快速充电覆盖率要达到80。交通运输部……2022年,用5G网络追光2022年,在5G方面有什么值得期待的?高通公司、ATT、Verizon和其他5G相关专家给我们预测5G在2022年将如何发展,以及该技术将推动哪些令人兴奋的新发展。如果……特斯拉起诉项立刚,后者回应积极应诉IT之家5月11日消息,根据信息显示,特斯拉汽车(北京)有限公司与项立刚等网络侵权责任纠纷一案新增开庭公告,原告为特斯拉汽车(北京)有限公司,案件将于5月24日在北京互联网法院……
9个叹为观止的微信小程序,个个好用不要钱,建议低调使用浙江圆通全力推进自动化上新迎旺季给想买特斯拉model3的小伙伴说几点注意事项1万块的手机,人人有份。三星为了回归中国市场,到底有多拼?2022,1月15日起。出租车是不是要涨价?买一部1000多的手机,选哪个牌子的性价比高一些?iQOONeo6骁龙880W快充,拼尽全力誓做K50劲敌,它俄罗斯5G设备断供后,欲投入9000亿翻身,华为及时雨救场苹果秋季发布会除iPhone13手机外,AirPods3和i南方电网公司董事长党组书记孟振平与华为公司副董事长轮值董事长iQOO宣布与歌手周深合作,同时公布合作曲生而为赢骁龙888的手机都出来了,那么现在骁龙870还能买吗?

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利