linuxjstack
‘壹’ linux镄刢pu璐熻浇杩囬珮linux镄刢pu璐熻浇
链嶅姟鍣–PU璐熻浇杩囬珮锛屽备綍瀹氢綅闂棰桡纻
涓涓搴旂敤鍗犵敤CPU寰堥珮锛岄櫎浜嗙‘瀹炴槸璁$畻瀵嗛泦鍨嫔簲鐢ㄤ箣澶栵纴阃氩父铡熷洜閮芥槸鍑虹幇浜嗘诲惊鐜銆侰PU璐熻浇杩囬珮瑙e喅闂棰樿繃绋嬶细
浣跨敤銆恡op銆戝懡浠ゅ畾浣嶅纾甯歌繘绋嬶纴鍙鍙戠幇12836镄凛PU鍜屽唴瀛桦崰鐢ㄧ巼閮介潪甯搁珮
澶囨敞锛歵op锻戒护榛樿ゆ儏鍐典笅锛屾槸姣3绉掑埛鏂颁竴娆°备篃鍙浠ラ氲繃top-d鍒锋柊镞堕棿闂撮殧>𨱒ユ寚瀹氩埛鏂伴戠巼锛屽伥op-d0.1鎴杢op-d0.01绛夈伥op镓ц屾椂锛屼篃鍙浠ユ寜钬渟钬濋敭锛屼慨鏀规椂闂撮棿闅斻
浣跨敤銆恡op-H-p杩涚▼鍙枫戞煡鐪嫔纾甯哥嚎绋
浣跨敤銆恜rintf"%xn"绾跨▼鍙枫戝皢寮傚父绾跨▼鍙疯浆鍖栦负16杩涘埗
浣跨敤銆恓stack杩涚▼鍙穦grep16杩涘埗寮傚父绾跨▼鍙-A90銆戞潵瀹氢綅寮傚父浠g爜镄勪綅缃锛堟渶钖庣殑-A90鏄镞ュ织琛屾暟锛屼篃鍙浠ヨ緭鍑轰负鏂囨湰鏂囦欢鎴栦娇鐢ㄥ叾浠栨暟瀛楋级銆傚彲浠ョ湅鍒板纾甯镐唬镰佺殑浣岖疆銆
镓惧埌鐩稿簲浠g爜妫镆ワ纴鍙戠幇纭瀹炴湁姝诲惊鐜瀛桦湪銆
鎺掓煡CPU鏁呴㱩镄勫父鐢ㄥ懡浠わ细
top锻戒护锛歀inux锻戒护銆傚彲浠ユ煡鐪嫔疄镞剁殑CPU浣跨敤𨱍呭喌銆备篃鍙浠ユ煡鐪嬫渶杩戜竴娈垫椂闂寸殑CPU浣跨敤𨱍呭喌銆
PS锻戒护锛歀inux锻戒护銆傚己澶х殑杩涚▼鐘舵佺洃鎺у懡浠ゃ傚彲浠ユ煡鐪嬭繘绋嬩互鍙婅繘绋嬩腑绾跨▼镄勫綋鍓岰PU浣跨敤𨱍呭喌銆傚睘浜庡綋鍓岖姸镐佺殑閲囨牱鏁版嵁銆
jstack锛钦ava鎻愪緵镄勫懡浠ゃ傚彲浠ユ煡鐪嬫煇涓杩涚▼镄勫綋鍓岖嚎绋嬫爤杩愯屾儏鍐点傛牴鎹杩欎釜锻戒护镄勮緭鍑哄彲浠ュ畾浣嶆煇涓杩涚▼镄勬墍链夌嚎绋嬬殑褰揿墠杩愯岀姸镐併佽繍琛屼唬镰侊纴浠ュ强鏄钖︽婚挛绛夌瓑銆
pstack锛歀inux锻戒护銆傚彲浠ユ煡鐪嬫煇涓杩涚▼镄勫綋鍓岖嚎绋嬫爤杩愯屾儏鍐点
‘贰’ linux系统怎么对java应用程序进行性能分析
分析CPU占用的方法和手段:
1. top命令:可以查看实时的CPU使用情况。
2. ps -ef命令:可以查看雹凳纤进程以及进程中线程的当前CPU使用情况以及属于当前状态的采样数据。
3. jstack:Java提供的命令。可以查看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等粗宽。
4. pstack:Linux命令。可以查看某个进程的当前线程栈运行情况
分析内存性能的方法和技巧:
1.top命令:可以查看实时的内存使用情况。
2.jmap -histo:live [pid],然后分析具体的对象源仿数目和占用内存大小,从而定位代码。
jmap -mp:live,format=b,file=xxx.xxx [pid],然后利用MAT工具分析是否存在内存泄漏等等。
‘叁’ linux cpu使用率过高排查
方法一
第一步:使用
top命令,然后按shift+p按照CPU排序
找到占用CPU过高的进程的pid
第二步:使用
top -H -p [进程id]
找到进程中消耗资源最高的线程的id
第三步:使用
echo 'obase=16;[线程id]' | bc或者printf "%x
" [线程id]
将线程id转换为16进制(字母要小写)
bc是linux的计算器命令
第四步:执行
jstack [进程id] |grep -A 10 [线程id的16进制]”
查看线程状态信息
方法二
第一步:使用
top命令,然后按shift+p按照CPU排序
找到占用CPU过高的进程
第二步:使用
ps -mp pid -o THREAD,tid,time | sort -rn
获取线程信息,并找到占用CPU高的线程
第三步:使用
echo 'obase=16;[线程id]' | bc或者printf "%x
" [线程id]
将需要的线程ID转换为16进制格式
第四步:使用
jstack pid |grep tid -A 30 [线程id的16进制]
打印线程的堆栈信息
案例分析
场景描述
生产环境下JAVA进程高CPU占用故障排查
解决过程
1、根据top命令,发现PID为2633的Java进程占用CPU高达300%,出现故障。
2、找到该进程后,如何定位具体线程或代码呢,首先显示线程列表,并按照CPU占用高的线程排序:
1[root@localhost ~]# ps -mp 2633 -o THREAD,tid,time | sort -rn
显示结果如下:
化主动为被动的方式,一方面减轻了运维工程师的工作,另一方面也减小了运维漏看或者忽略告警的情况发生。
‘肆’ 原来jdk自带了这么好玩的工具——使用 jstack定位死循环
线程快照是java虚拟机内每一个线程正在执行的方法堆栈的集合,生成线程快照的主要目的是用于定位线程出现问题的位置;常见的问题有
命令格式
jstack的option参数并不多,真正用到的也就三个,接下来我们一个个介绍一下
- -F :当线程挂起(Suspended)时,使用jstack -l pid命令是不会打印堆栈信息的,使用-F则可以强制输出线程堆栈;但是会停止但
- -l :打印的信息除了堆栈外,还会显示锁芹梁返的附加信息;
- -m :同时输出java和C/C++的堆栈信息;在java的系统类库里面,有很多方法都是native修饰的,这些native修饰的方法你在java层面是看不到源码的,因为这些方法都是C/C++实现嫌饥的;
在线程的堆栈中,需要特别留意以下几种状态:
不带option参数的命令
打印结果如下
第一行各个单词的解析,
这里我们使用2个窗口,分别使用以下2个命令来测试
通过2个窗口对比可以看到,加了-l的命令多打印了锁的信息;
一般情况下,如果程序出错了, 都不会直接在生产环境的服务器上找错误,这个时候就可以用到一个非常实用的功能,将堆栈快照导出来,然后到别的电脑上看,命令如下
执行后,就可以看到文件已经导出来了
通过cat命令可以看到,里面的内容和我们在命令行输出的内容是一样的
首先我们准备好一个死循环的线程,在线程内定一个while的死循环,并且给这个线程起个名字为:yexindogn,阿里巴巴的开发规范里面有一个规定,就是每个线程必须起一个名字,起名字就是为了 以后程序出问题的时候好找错误;
接着我们将此代码打成jar包扔到linux服务器上运行,直接输入 java -jar Test.jar 命令即可运行,运行后我们可以看到控制台一直在输出112这个字符,这就代表程序已经在运行了;
接着在看下CPU的运行情况,使用top命令查看cpu占用情况,排在第一位的是进程号为30328的进程,占用了6.6%的cpu; 这边我使用了2个命令行连到同一台服务器,一个窗口用来运行刚刚的jar包,另一个窗口用来查找错误;
知道进程号了,接着就是找线程了,输入以下命令
打印结果如下,这里有一点需要注意,在我们加上-Hp指令后,PID展示就是线程的id了,这时候我们看到占用CPU最高的线程id是30365;
还有另一种方式,就是使用ps命令来查找线程
通过这个命令我们可以看到这边占用最高的线程id也是30365 ;
以上的方式我们成功找到了占用cpu高的线程id是30365,但这个id是十进制的,在这里需要先转为16进制,输入命令
计算出对应的16进制为:769d
当然也可以用其他的计算工具,比如mac系统自带计算器就支持进制之间的转换
在命令行输入以下命令,这种方法更加快速,推荐使用
其中,grep 命令是查找结果为769d的内容,-A 20 表示打印匹配所在行的后20行内容。直接帮我们定位到所在线程的堆栈,结果如下
当然也可以用下面的死办法,先打印出所有的堆栈快照;
打印结果如下
接着我用刚刚计算出来的16进制复制出来在这里搜索一下,经过查看就知道是我们刚刚起了名字为yexindong的线程出错了,出错的位置在Test.java的第13行代码
我们看看java代码,确实是第13行这里的死循环导致的
首先打开任务管理器,因为默认windows的任务管理器是不显示进程pid的,所以我们需要设置一下,选择 查看 选择列(S)...
选中PID进程表示符后点击确定按钮
然后我们就可以看到占用CPU最高的java进程PID为:976
因为windows不能直接查看java进程中的线程信息,所以我们需要借助一个工具,渣指这个工具是微软自己开发的,叫做Process Explorer ,网上很多,需要的童鞋请自行网络,打开后找到pid为976的进程右击选择 属性
在弹出的窗口中找到线程这一栏,它的排序默认就是按照cpu占用的率倒序排列的,所以最上面的就是占用cpu最高的线程了,记住它的线程id:3548
刚刚拿到的进程id是十进制的,但是我们导出的jstack信息里面,线程id是以16进制来展示的,所以我们要先将这个线程id为3548转为16进制的,使用windows自带的计算器即可,在快捷命令行输入calc
计算器打开后将其设置为程序员使用的计算器
接着输入线程id3548,在按一下16进制,就会自动进行转换,结果为ddc,记住这个16进制;
在命令行输入以下指令导出进程的堆栈快照信息
几秒钟后,快照导出了,静静地躺在文件夹里,等待着我们打开
用Notepad++打开导出的文件,搜索刚刚计算出来的16进制ddc,就可以定位到线程出错的位置了
有些童鞋可能会觉得用这个jstack命令麻烦了,那java在代码里面可不可以打印出堆栈呢?你别说,还真有,就是这个方法:Thread.getAllStackTraces();光说不练假把式,来个demo测试一下吧
执行后打印结果如下,由此可以看到,将当前进程的所有线程都打印出来了,但是这边只打印了简单的堆栈信息,对于开发人员来说,已经起到了监控作用;
作为调优和找错的工具来说,可以说jstack是用的最多的一个工具了,但是由于局限性,现在已经慢慢被替换掉了;大家更倾向于使用阿里巴巴开发的工具arthas;感兴趣的童鞋可以了解下!
‘伍’ 【26期】内存持续上升,如何排查
当内存持续上升时,可以采取以下方法和工具进行排查:
1. 使用Linux命令行工具
top命令:使用top命令实时显示进程的CPU和内存使用情况。通过top Hp pid可以查看特定线程的资源占用情况,帮助识别哪些线程或进程占用了大量内存。
vmstat命令:虽然vmstat主要用于观察进程的上下文切换,但它也能提供系统的内存和CPU使用情况,有助于了解整体资源状况。
pidstat命令:通过pidstat p pid r 1 3等参数,可以深入到线程级别监测内存使用情况,进一步细化问题定位。
2. 针对Java应用的工具
jstat命令:对于Java应用,jstat可以实时监控堆内存和垃圾回收情况,帮助识别内存泄漏或垃圾回收效率低下的问题。
jmap命令:jmap用于查看堆内存配置和详细使用情况。通过jmap histo[:live] pid可以查看对象的统计信息,有助于识别哪些对象占用了大量内存。
jstack命令:jstack用于分析线程堆栈,有助于排查死锁问题。虽然它主要关注线程状态,但有时线程状态也能间接反映内存使用情况。
总结:
- 排查内存问题需要综合运用多种工具和方法。
- 在Linux环境下,top、vmstat和pidstat等命令行工具是常用的内存监控和分析手段。
- 对于Java应用,jstat、jmap和jstack等工具则提供了更深入的内存分析和线程堆栈分析功能。
- 排查过程可能需要结合源码分析,并不断学习和实践,才能准确找出问题根源。