java performance analysis

jps 分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
* jps位于jdk的bin目录下,其作用是显示当前系统的java进程情况,及其id号
* jps并不使用应用程序名来查找JVM实例,因此,它查找所有的Java应用程序(包括即使没有使用java执行体的那种(例如:定制的启动器))
* jps仅查找当前用户的Java进程,而不是当前系统中的所有进程


JDK中的jps命令可以显示当前运行的java进程以及相关参数,它的实现机制如下:
java程序在启动以后,会在"java.io.tmpdir"指定的目录下,就是临时文件夹里,生成一个类似于"hsperfdata_User"的文件夹,在这个文件夹里(Linux中为/tmp/hsperfdata_{userName}/),有几个文件,名字就是java进程的pid,因此列出当前运行的java进程,只是把这个目录里的文件名列一下而已.
例如:
[wisdom@10 ~]$ ls -ld /tmp/hsperfdata_*
drwxr-xr-x 2 root root 4096 Mar 7 14:47 /tmp/hsperfdata_root
drwxr-xr-x 2 wisdom wisdom 4096 Mar 7 14:49 /tmp/hsperfdata_wisdom


例如:
[wisdom@10 ~]$ jps
1347 Elasticsearch
12662 Jps
16731 QuorumPeerMain
17084 Kafka
21790 Main

# -q 只显示pid,不显示class名称,jar文件名和传递给main 方法的参数
[wisdom@10 ~]$ jps -q
1347
16731
17084
14093
21790

# -m 输出传递给main方法的参数,在嵌入式jvm上可能是null,在这里,在启动main方法的时候,我给String[] args传递两个参数
[wisdom@10 ~]$ jps -m
1347 Elasticsearch start -d -p /mnt/app/elasticsearch/elasticsearch.pid
16731 QuorumPeerMain /mnt/app/zookeeper/bin/../conf/zoo.cfg
17084 Kafka /mnt/app/kafka/config/server.properties
21790 Main --1.9 /mnt/app/logstash/lib/bootstrap/environment.rb logstash/runner.rb agent -f /mnt/app/logstash/config/logstash-ssp-4502.conf -l /mnt/log/logstash/logstash-4502.log
14287 Jps -m

# -l 输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名
[wisdom@10 ~]$ jps -l
1347 org.elasticsearch.bootstrap.Elasticsearch
16731 org.apache.zookeeper.server.quorum.QuorumPeerMain
17084 kafka.Kafka
16094 sun.tools.jps.Jps
21790 org.jruby.Main

# -v 输出传递给JVM的参数
[wisdom@10 ~]$ jps -v
1347 Elasticsearch -Xms5g -Xmx5g -Djava.awt.headless=true -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8 -Djna.nosys=true -Des.path.home=/mnt/app/elasticsearch
16731 QuorumPeerMain -Dzookeeper.log.dir=/mnt/log/zookeeper -Dzookeeper.root.logger=INFO,CONSOLE -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false
17084 Kafka -Xmx1G -Xms1G -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+DisableExplicitGC -Djava.awt.headless=true -Xloggc:/mnt/log/kafka/kafkaServer-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/mnt/log/kafka -Dlog4j.configuration=file:/mnt/app/kafka/bin/../config/log4j.properties
16637 Jps -Denv.class.path=.:/mnt/app/java/lib:/mnt/app/java/jre/lib -Dapplication.home=/mnt/app/java -Xms8m
21790 Main -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -Djava.awt.headless=true -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -Xmx1g -Xss2048k -Djffi.boot.library.path=/mnt/app/logstash/vendor/jruby/lib/jni -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -Djava.awt.headless=true -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/mnt/app/logstash/heapdump.hprof -Xbootclasspath/a:/mnt/app/logstash/vendor/jruby/lib/jruby.jar -Djruby.home=/mnt/app/logstash/vendor/jruby -Djruby.lib=/mnt/app/logstash/vendor/jruby/lib -Djruby.script=jruby -Djruby.shell=/bin/sh


拓展:JPS失效处理
现象: 用"ps -ef|grep java"能看到启动的java进程,但是用jps查看却不存在该进程的id.jconsole,jvisualvm可能无法监控该进程,其他java自带工具也可能无法使用
分析: jps,jconsole,jvisualvm等工具的数据来源就是这个文件(/tmp/hsperfdata_{username}/pid).所以当该文件不存在或是无法读取时就会出现jps无法查看该进程号,jconsole无法监控等问题
原因:
1.磁盘读写,目录权限问题
若该用户没有权限写/tmp目录或是磁盘已满,则无法创建/tmp/hsperfdata_{username}/pid文件.或该文件已经生成,但用户没有读权限
2.临时文件丢失,被删除或是定期清理
对于linux机器,一般都会存在定时任务对临时文件夹进行清理,导致/tmp目录被清空.常用的可能定时删除临时目录的工具为crontab,redhat的tmpwatch,ubuntu的tmpreaper等.这个导致的现象可能会是这样,用jconsole监控进程,发现在某一时段后进程仍然存在,但是却没有监控信息了
3.java进程信息文件存储地址被设置不在/tmp目录下
java默认会在/tmp/hsperfdata_{username}目录保存进程信息,但由于以上1,2所述原因,可能导致该文件无法生成或是丢失,所以java启动时提供了参数(-Djava.io.tmpdir),可以对这个文件的位置进行设置,而jps,jconsole都只会从"/tmp"目录读取,而无法从设置后的目录读物信息