您的位置:首页 > 编程语言 > Java开发

java 性能问题排查

2016-11-30 00:00 253 查看

cpu占用率过高

1) 首先能过top查看cpu过高的pid,而后通过ps -ef |grep pid查看进程的详细信息。

2) 接着查看每个线程占用的cpu占用率,ps -mp pid -o THREAD,tid,time | sort -rn
或者 通过 top -H -p pid

3) 转换,而后通过比较查看哪个占用过高, 其次将需要的线程ID转换为16进制格式:printf "%x\n" tid

得。

4) jstack pid |grep tid -A 30 ,jstack 可以查看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等。

5) 最后就根据得到的信息分析 代码,看哪块会出现问题 。

实战

今天出现了一个问题,集成代码上线后,系统卡死,无法访问,初看日志也没有问题,而后top查看,cpu果然占用100%+;

而后根据如上操作,找到线程id,而后jstack 查看 ,dump信息如下,原来是syslog 出现了问题。

Thread 9099: (state = IN_VM)
- java.net.PlainDatagramSocketImpl.datagramSocketCreate() @bci=0 (Compiled frame; information may be imprecise)
- java.net.AbstractPlainDatagramSocketImpl.create() @bci=15, line=83 (Compiled frame)
- java.net.DatagramSocket.createImpl() @bci=61, line=342 (Compiled frame)
- java.net.DatagramSocket.<init>() @bci=56, line=199 (Compiled frame)
- UDPTest.send() @bci=31, line=35 (Compiled frame)

原生 系统中是有日志记录的,因为项目需求,需要将日志上报syslog服务器,因此需要在记录日志的地方,在调一个syslog的接口,从dump发现,syslog出了问题。但是调用syslog的过程的代码,没发现什么异常。接着我们就去查看syslog的源码,发现确实有问题,如下send方法内形成死循环。现在解决方案就明确了。如果在send异常时,var5 并没有任何变化。如果socket一直异常,则会无限循环。并没有按照设定的值重试。

byte var5 = 0;

while(var5 != -1 && var5 < this.netSyslogConfig.getWriteRetries() + 1) {
try {
this.socket.send(var4);
var5 = -1;
} catch (IOException var7) {
if(var5 == this.netSyslogConfig.getWriteRetries() + 1) {
throw new SyslogRuntimeException(var7);
}
}
}


内存占用过高( 堆 )

1)一般内存分析 使用 jdk自带 的 jmap jhat

jps -ml //查看pid

jmap -heap 9142  //  打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.

jmap -histo:live 9142 |head -n 20

jmap -F -dump:format=b,file=test.bin 14424

jhat test.bin

访问 http://localhost:7000
也可通过

2) 设置虚拟机参数为:-Xmx40m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=E:\Java\dump

然后用 jprofile 工具分析 内存 dump文件

通常我们在开发中经常遇到的OutOfMemoryError 有 PermGen space(永久代) Java heap space(堆

Java内存模型是描述Java程序中各变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存取出变量这样的低层细节。

在Java虚拟机中,内存分为三个代:新生代(New)、老生代(Old)、永久代(Perm)。

(1)新生代New:新建的对象都存放这里

(2)老生代Old:存放从新生代New中迁移过来的生命周期较久的对象。新生代New和老生代Old共同组成了堆内存。

(3)永久代Perm:是非堆内存的组成部分。主要存放加载的Class类级对象如class本身,method,field等等。

如果出现java.lang.OutOfMemoryError: Java heap space异常,说明Java虚拟机的堆内存不够。原因有二:

(1)Java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整。

(2)代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。

如果出现java.lang.OutOfMemoryError: PermGen space,说明是Java虚拟机对永久代Perm内存设置不够。

一般出现这种情况,都是程序启动需要加载大量的第三方jar包。例如:在一个Tomcat下部署了太多的应用。

当遇到 heap space异常,时,要通过分析代码,减少不必要的对象创建,同时避免内存泄漏。

1)top 查看占用率用的pid

2) jmap -histo:live [pid] > result.log ,然后分析具体的对象数目和占用内存大小,从而定位代码。

如下 一般占用较高的 constMethodKlass、methodKlass、constantPoolKlass 这些类信息。而遇到 问题的时候 我们应该重点分析 数组,集合,类等占据大量内存的类。


http://www.ibm.com/developerworks/cn/java/j-lo-performance-tuning-practice/ http://blog.csdn.net/blade2001/article/details/9066001 http://www.cnblogs.com/chy2055/p/5124040.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: