[b]一、JVM基础知识[/b]
比较多,转载下吧
[url]http://blog.csdn.net/jimmy1980/article/details/4968308[/url]
[url]http://my.oschina.net/shootercn/blog/15393[/url]
两篇内容一样,第二篇加了几个图
[b]二、JVM监控工具[/b]
jdk自带了需要有用的轻量级的监控工具,对解决性能问题非常有用,一般情况使用它们足够解决问题。
[b]下面介绍下jstack,jconsole,jmap,jstat的用法[/b]
[b]1、jconsole[/b]
1、服务器Tomcat catalina.sh 设置
JAVA_OPTS="-server -Xms2048M -Xmx2048M -Xss256K -Djava.awt.headless=true -XX:PermSize=256M -XX:MaxPermSize=512m -XX:SurvivorRatio=6 -XX:+PrintGC -Xloggc:/app/tomcat_gc.log [b]-Dcom.sun.management.jmxremote.port=8181 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=203.81.21.100[/b]"
2、客户机cmd 调用jconsole
jconsole service:jmx:rmi:///jndi/rmi://203.81.21.100:8181/jmxrmi
可能出现连接失败的情况:
(1)防火墙问题
可能是服务器的8181端口禁止访问,可以通过本机 telnet命令测试一下端口是否可以访问。
(2)hostname问题
这个也是经常遇到的,可能是服务器的/etc/hosts文件的 ip指向了127.0.0.1,执行 hostname -i 可以看看是否正确,如果指向了127.0.0.1,修改 /etc/hosts文件,增加真实的IP地址,然后执行hostname -i是否指到真实的IP地址,另外很多情况下,需要重新启动服务器(reboot,不是重新启动tomcat)方可生效。
[b]2、jstack[/b]
jstack(linux下特有)
可以观察到jvm中当前所有线程的运行情况和线程当前状态
jstack 2083 --2083是pid,可以通过ps命令得到
与jconsole中的线程部分,功能一致
[b]3、jmap[/b]
jmap(linux下特有,也是很常用的一个命令)
观察运行中的jvm物理内存的占用情况。
参数如下:
-heap:打印jvm heap的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :同上,但是只答应存活对象的情况
-permstat:打印permanent generation heap情况
命令使用:
jmap -heap 2083
可以观察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存使用情况
输出内容:
jmap -histo 2083 | jmap -histo:live 2083
可以观察heap中所有对象的情况(heap中所有生存的对象的情况)。包括对象数量和所占空间大小。
输出内容:
写个脚本,可以很快把占用heap最大的对象找出来,对付内存泄漏特别有效。
jmap -histo 2083输出内容如下:
num #instances #bytes class name
--------------------------------------
1: 427398 14458448 [I
2: 178798 6830216 [C
3: 50278 6668512 <constMethodKlass>
4: 179924 4318176 java.lang.String
5: 50278 4026648 <methodKlass>
6: 15244 3894200 [B
7: 47809 1773776 [Ljava.lang.Object;
...
...
...
Total 1645187 81806088
#instance是对象的实例个数 #bytes是总占用的字节数
class name对应的就是Class文件里的class的标识
B代表byte
C代表char
D代表double
F代表float
I代表int
J代表long
Z代表boolean
前边有[代表数组,[I 就相当于int[]
对象数字用[L+类名表示
[b]4、jstat[/b]
最后要重点介绍下这个命令。
这是jdk命令中比较重要,也是相当实用的一个命令,可以观察到classloader,compiler,gc相关信息
具体参数如下:
-class:统计class loader行为信息
-compile:统计编译行为信息
-gc:统计jdk gc时heap信息
-gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区)相应的heap容量情况
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件
-gcnew:统计gc时,新生代的情况
-gcnewcapacity:统计gc时,新生代heap容量
-gcold:统计gc时,老年区的情况
-gcoldcapacity:统计gc时,老年区heap容量
-gcpermcapacity:统计gc时,permanent区heap容量
-gcutil:统计gc时,heap情况
-printcompilation:不知道干什么的,一直没用过。
一般比较常用的几个参数是:
jstat -class 2083 1000 10 (2083是pid,每隔1秒监控一次,一共做10次)
输出内容含义如下:
Loaded Number of classes loaded.
Bytes Number of Kbytes loaded.
Unloaded Number of classes unloaded.
Bytes Number of Kbytes unloaded.
Time Time spent performing class load and unload operations.
jstat -gc 2083 2000 20(每隔2秒监控一次,共做10)
输出内容含义如下:
S0C Current survivor(存活的) space 0 capacity (KB).
EC Current eden space capacity (KB).
EU Eden space utilization (KB).
OC Current old space capacity (KB).
OU Old space utilization (KB).
PC Current permanent space capacity (KB).
PU Permanent space utilization (KB).
YGC Number of young generation GC Events.
YGCT Young generation garbage collection time.
FGC Number of full GC events.
FGCT Full garbage collection time.
GCT Total garbage collection time.
监控内存使用情况 参数 (查看内存溢出相对有用)
jstat -gccause 2083 5000 (每隔5秒监控一次)
[b]三、个人曾遇到的问题[/b]
我曾经通过jmap、jconsole、以及printGC信息分析解决了一个性能问题。
问题现象,tomcat不定期宕机,宕机是系统进行疯狂的Full GC,导致CPU居高不下,而且Full GC 并没有回收垃圾,Tenured Generation堆空间一直占满,不断引发Full GC。从jconsole和printGC都可以明显的看到这个现象。
不难看出,这是由于对象无法回收引起的。
通过linux定时每半小时生成jmap -histo的日志文件,不断分析宕机时刻的堆中对象的情况,找到了相应的业务类对象,该对象每次宕机时都大量出现,并与Date对象成1:2的数量比例,该业务类的toString方法中恰好有创建两个Date对象;
确定了该类之后,查找代码,终于在一个页面中找到了一行代码,以前的开发人员遗留了一行测试代码,加载了极大数量的该对象,一旦有人用到该页面功能,就会导致问题。
比较多,转载下吧
[url]http://blog.csdn.net/jimmy1980/article/details/4968308[/url]
[url]http://my.oschina.net/shootercn/blog/15393[/url]
两篇内容一样,第二篇加了几个图
[b]二、JVM监控工具[/b]
jdk自带了需要有用的轻量级的监控工具,对解决性能问题非常有用,一般情况使用它们足够解决问题。
[b]下面介绍下jstack,jconsole,jmap,jstat的用法[/b]
[b]1、jconsole[/b]
1、服务器Tomcat catalina.sh 设置
JAVA_OPTS="-server -Xms2048M -Xmx2048M -Xss256K -Djava.awt.headless=true -XX:PermSize=256M -XX:MaxPermSize=512m -XX:SurvivorRatio=6 -XX:+PrintGC -Xloggc:/app/tomcat_gc.log [b]-Dcom.sun.management.jmxremote.port=8181 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=203.81.21.100[/b]"
2、客户机cmd 调用jconsole
jconsole service:jmx:rmi:///jndi/rmi://203.81.21.100:8181/jmxrmi
可能出现连接失败的情况:
(1)防火墙问题
可能是服务器的8181端口禁止访问,可以通过本机 telnet命令测试一下端口是否可以访问。
(2)hostname问题
这个也是经常遇到的,可能是服务器的/etc/hosts文件的 ip指向了127.0.0.1,执行 hostname -i 可以看看是否正确,如果指向了127.0.0.1,修改 /etc/hosts文件,增加真实的IP地址,然后执行hostname -i是否指到真实的IP地址,另外很多情况下,需要重新启动服务器(reboot,不是重新启动tomcat)方可生效。
[b]2、jstack[/b]
jstack(linux下特有)
可以观察到jvm中当前所有线程的运行情况和线程当前状态
jstack 2083 --2083是pid,可以通过ps命令得到
与jconsole中的线程部分,功能一致
[b]3、jmap[/b]
jmap(linux下特有,也是很常用的一个命令)
观察运行中的jvm物理内存的占用情况。
参数如下:
-heap:打印jvm heap的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :同上,但是只答应存活对象的情况
-permstat:打印permanent generation heap情况
命令使用:
jmap -heap 2083
可以观察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存使用情况
输出内容:
jmap -histo 2083 | jmap -histo:live 2083
可以观察heap中所有对象的情况(heap中所有生存的对象的情况)。包括对象数量和所占空间大小。
输出内容:
写个脚本,可以很快把占用heap最大的对象找出来,对付内存泄漏特别有效。
jmap -histo 2083输出内容如下:
num #instances #bytes class name
--------------------------------------
1: 427398 14458448 [I
2: 178798 6830216 [C
3: 50278 6668512 <constMethodKlass>
4: 179924 4318176 java.lang.String
5: 50278 4026648 <methodKlass>
6: 15244 3894200 [B
7: 47809 1773776 [Ljava.lang.Object;
...
...
...
Total 1645187 81806088
#instance是对象的实例个数 #bytes是总占用的字节数
class name对应的就是Class文件里的class的标识
B代表byte
C代表char
D代表double
F代表float
I代表int
J代表long
Z代表boolean
前边有[代表数组,[I 就相当于int[]
对象数字用[L+类名表示
[b]4、jstat[/b]
最后要重点介绍下这个命令。
这是jdk命令中比较重要,也是相当实用的一个命令,可以观察到classloader,compiler,gc相关信息
具体参数如下:
-class:统计class loader行为信息
-compile:统计编译行为信息
-gc:统计jdk gc时heap信息
-gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区)相应的heap容量情况
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件
-gcnew:统计gc时,新生代的情况
-gcnewcapacity:统计gc时,新生代heap容量
-gcold:统计gc时,老年区的情况
-gcoldcapacity:统计gc时,老年区heap容量
-gcpermcapacity:统计gc时,permanent区heap容量
-gcutil:统计gc时,heap情况
-printcompilation:不知道干什么的,一直没用过。
一般比较常用的几个参数是:
jstat -class 2083 1000 10 (2083是pid,每隔1秒监控一次,一共做10次)
输出内容含义如下:
Loaded Number of classes loaded.
Bytes Number of Kbytes loaded.
Unloaded Number of classes unloaded.
Bytes Number of Kbytes unloaded.
Time Time spent performing class load and unload operations.
jstat -gc 2083 2000 20(每隔2秒监控一次,共做10)
输出内容含义如下:
S0C Current survivor(存活的) space 0 capacity (KB).
EC Current eden space capacity (KB).
EU Eden space utilization (KB).
OC Current old space capacity (KB).
OU Old space utilization (KB).
PC Current permanent space capacity (KB).
PU Permanent space utilization (KB).
YGC Number of young generation GC Events.
YGCT Young generation garbage collection time.
FGC Number of full GC events.
FGCT Full garbage collection time.
GCT Total garbage collection time.
监控内存使用情况 参数 (查看内存溢出相对有用)
jstat -gccause 2083 5000 (每隔5秒监控一次)
[b]三、个人曾遇到的问题[/b]
我曾经通过jmap、jconsole、以及printGC信息分析解决了一个性能问题。
问题现象,tomcat不定期宕机,宕机是系统进行疯狂的Full GC,导致CPU居高不下,而且Full GC 并没有回收垃圾,Tenured Generation堆空间一直占满,不断引发Full GC。从jconsole和printGC都可以明显的看到这个现象。
不难看出,这是由于对象无法回收引起的。
通过linux定时每半小时生成jmap -histo的日志文件,不断分析宕机时刻的堆中对象的情况,找到了相应的业务类对象,该对象每次宕机时都大量出现,并与Date对象成1:2的数量比例,该业务类的toString方法中恰好有创建两个Date对象;
确定了该类之后,查找代码,终于在一个页面中找到了一行代码,以前的开发人员遗留了一行测试代码,加载了极大数量的该对象,一旦有人用到该页面功能,就会导致问题。