top
top介绍:
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。
top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止该程序为止. 比较准确的说,top命令提供了实时的对系统处理器的状态监视.它将显示系统中CPU最“敏感”的任务列表.该命令可以按CPU使用.内存使用和执行时间对任务进行排序;而且该命令的很多特性都可以通过交互式命令或者在个人定制文件中进行设定.
top命令监控的最小单位是进程。所以对程序进行分析是还需要其他命令来协同分析。通常利用jps、ps、netstat、jstack、pmap、jmap命令一起使用。主要讲jstack和jmap
top使用方法:
使用格式:
top [-] [d] [p] [q] [c] [C] [S] [s] [n]
参数说明:
d:指定每两次屏幕信息刷新之间的时间间隔。当然用户可以使用s交互命令来改变之。
p:通过指定监控进程ID来仅仅监控某个进程的状态。
q:该选项将使top没有任何延迟的进行刷新。如果调用程序有超级用户权限,那么top将以尽可能高的优先级运行。
S:指定累计模式。
s:使top命令在安全模式中运行。这将去除交互命令所带来的潜在危险。
i:使top不显示任何闲置或者僵死进程。
c:显示整个命令行而不只是显示命令名。
常用命令说明:
Ctrl+L:擦除并且重写屏幕
K:终止一个进程。系统将提示用户输入需要终止的进程PID,以及需要发送给该进程什么样的信号。一般的终止进程可以使用15信号;如果不能正常结束那就使用信号9强制结束该进程。默认值是信号15。在安全模式中此命令被屏蔽。
i:忽略闲置和僵死进程。这是一个开关式命令。
q:退出程序
r:重新安排一个进程的优先级别。系统提示用户输入需要改变的进程PID以及需要设置的进程优先级值。输入一个正值将使优先级降低,反之则可以使该进程拥有更高的优先权。默认值是10。
S:切换到累计模式。
s:改变两次刷新之间的延迟时间。系统将提示用户输入新的时间,单位为s。如果有小数,就换算成m s。输入0值则系统将不断刷新,默认值是5 s。需要注意的是如果设置太小的时间,很可能会引起不断刷新,从而根本来不及看清显示的情况,而且系统负载也会大大增加。
f或者F:从当前显示中添加或者删除项目。
o或者O:改变显示项目的顺序
l:切换显示平均负载和启动时间信息。
m:切换显示内存信息。
t:切换显示进程和CPU状态信息。
c:切换显示命令名称和完整命令行。
M:根据驻留内存大小进行排序。
P:根据CPU使用百分比大小进行排序。
T:根据时间/累计时间进行排序。
W:将当前设置写入~/.toprc文件中。
top补充命令:
监控java线程数:
ps -eLf | grep java | wc -l
监控网络客户连接数:
netstat -n | grep tcp | grep 侦听端口 | wc -l
获取某进程中运行中的线程数量:
ls /proc/PID/task | wc -l
top - 13:15:54 up 12 days, 23:03, 1 user, load average: 0.00, 0.02, 0.00
Tasks: 117 total, 1 running, 116 sleeping, 0 stopped, 0 zombie
Cpu(s): 1.2%us, 0.3%sy, 0.0%ni, 98.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 7675264k total, 2383792k used, 5291472k free, 175900k buffers
Swap: 0k total, 0k used, 0k free, 906540k cached
第一行:系统整体信息
13:15:54当前时间
12 days, 23:03系统运行时间
1 user 当前登录用户数
load average: 0.00, 0.02, 0.00 系统负载,即任务队列的平均长度。三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值。
第二行:进程信息
total 进程总数
running 正在运行的进程数
sleeping 睡眠的进程数
stopped 停止的进程数
zombie 僵尸进程数
第三行:Cpu(s): cpu信息
1.2%us 用户空间占用CPU百分比
0.3%sy 内核空间占用CPU百分比
0.0%ni 用户进程空间内改变过优先级的进程占用CPU百分比
98.5%id 空闲CPU百分比
0.0%wa等待输入输出的CPU时间百分比
0.0%hi 硬件CPU中断占用百分比
0.0%si 软中断占用百分比
0.0%st 虚拟机占用百分比
第四行:Mem: 内存信息
7675264k total 物理内存总量
2383792k used 使用的物理内存总量
5291472k free 空闲内存总量
175900k buffers 用作内核缓存的内存量
第五行:Swap: 交换区信息
0k total 交换区总量
0k used 使用的交换区总量
0k free 空闲交换区总量
906540k cached 缓冲的交换区总量,内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖,该数值即为这些内容已存在于内存中的交换区的大小,相应的内存再次被换出时可不必再对交换区写入。
各进程状态监控:
PID:进程ID,进程的唯一标识符
USER:进程所有者的实际用户名。
PR:进程的调度优先级。这个字段的一些值是'rt'。这意味这这些进程运行在实时态。
NI:进程的nice值(优先级)。越小的值意味着越高的优先级。负值表示高优先级,正值表示低优先级
VIRT:进程使用的虚拟内存。进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
RES:驻留内存大小。驻留内存是任务使用的非交换物理内存大小。进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
SHR:SHR是进程使用的共享内存。共享内存大小,单位kb
S:这个是进程的状态。它有以下不同的值:
D - 不可中断的睡眠态。
R – 运行态
S – 睡眠态
T – 被跟踪或已停止
Z – 僵尸态
%CPU:自从上一次更新时到现在任务所使用的CPU时间百分比。
%MEM:进程使用的可用物理内存百分比。
TIME+:任务启动后到现在所使用的全部CPU时间,精确到百分之一秒。
COMMAND:运行进程所使用的命令。进程名称(命令名/命令行)
jstack
jstack介绍:
通过jstack -l PID,我们可以知道jvm当前的各个线程当前的状态
jstack 分析:
jstack -l PID > jstack.log,将线程信息输出到jstack.log文本文件中,文本文件中部分内容如下:
"pool-1-thread-1①" #20 prio=5② os_prio=0③ tid=0x00007ff268f68800④ nid=0x2db5⑤ runnable [0x00007ff2831f2000⑥]
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 java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
- locked <0x00000000902fdcd0⑨> (a java.io.BufferedInputStream)
at org.apache.commons.httpclient.HttpParser.readRawLine(HttpParser.java:78)
at org.apache.commons.httpclient.HttpParser.readLine(HttpParser.java:106)
at org.apache.commons.httpclient.HttpConnection.readLine(HttpConnection.java:1116)
at org.apache.commons.httpclient.HttpMethodBase.readStatusLine(HttpMethodBase.java:1973)
at org.apache.commons.httpclient.HttpMethodBase.readResponse(HttpMethodBase.java:1735)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1098)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
at cn.saturn.web.utils.HttpTookit.doGet(HttpTookit.java:75)
at cn.saturn.web.center.SendCenter.SendDayline(SendCenter.java:77)
at cn.saturn.web.utils.QuartzJob.dayline(QuartzJob.java:98)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run⑧(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- <0x000000008bb1b1a8⑨> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"MySQL Statement Cancellation Timer" #19 daemon prio=5 os_prio=0 tid=0x00007ff26a10e000 nid=0x2db4 in Object.wait() [0x00007ff2836f4000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000008b8a84d0> (a java.util.TaskQueue)
at java.lang.Object.wait(Object.java:502)
at java.util.TimerThread.mainLoop(Timer.java:526)
- locked <0x000000008b8a84d0> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
Locked ownable synchronizers:
- None
java代码:
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {// ⑧
// TODO Auto-generated method stub
synchronized("资源名称⑨") {
}
TimeUnit.SECONDS.sleep(1);// ⑨
wait();// ⑨
}
}, "线程名②");
thread.setPriority(0);// ②
thread.setName("线程名");// ①
thread.getId();// ④
thread.getState();// ⑦
}
备注:
①线程名
②线程优先级
③
④java线程id
⑤java线程id映射的操作系统系统中的线程id
⑥线程栈的其实地址
⑦线程状态
⑧java代码中的线程执行位置
⑨资源名称(处于锁状态或处于锁释放状态或等待某资源释放锁)
线程状态:
死锁,Deadlock(重点关注)
运行中,Runnable
等待资源,Waiting on condition(重点关注)
等待获取监视器,Waiting on monitor entry(重点关注)
暂停,Suspended
对象等待中,Object.wait() 或 TIMED_WAITING
阻塞,Blocked(重点关注)
停止,Parked
重点关注代码补充:
死锁:
private static Object o1 = new Object();
private static Object o2 = new Object();
private static void deadLock() {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (o1) {
System.out.println(o1.hashCode());
synchronized (o2) {
System.out.println(o2.hashCode());
}
}
}
}
}, "deadLock1").start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (o2) {
System.out.println(o2.hashCode());
synchronized (o1) {
System.out.println(o1.hashCode());
}
}
}
}
}, "deadLock2").start();
}
等待资源:
1、sleep
2、读取大量资源时,而该资源使用了锁
3、网络太繁忙
4、其他线程在在执行
等待获取监视器:
使用synchronized(obj){
}
1、代码申请进入临界区,而此时obj对象的Monitor被其他线程占有,则该线程就会进入EntrySet中等待
2、代码申请进入临界区,而此时obj对象获取到Monitor,但是该线程还没有达到执行条件,则该线程就会进入WaitSet中等待
阻塞:
sleep、lock、synchronized、wait都会使线程进入阻塞状态
jmap
jmap介绍:
使用jmap -dump:live,format=b,file=m.hprof PID生成dump文件,通过分析dump文件来分析程序
dump文件分析:
1、使用上面的命令手动将dump文件导出(文件会很大)
2、下载dump文件分析工具(ftp://public.dhe.ibm.com/software/websphere/appserv/support/tools/jca/jca461.jar)或者在linux上安装dump文件分析软件(http://www.eclipse.org/mat/downloads.php)或将dump文件导入到eclipse上分析(eclipse需要安装mat插件)
3、分析
ps -mp 15851 -o THREAD,tid,time
printf "%x\n" 15867
jstack -l 15851 | grep 3dfb -A 60