转载 http://hi.baidu.com/higkoo/blog/item/f2583266e90e032aab184caf.html
阅读本文之前建立对Java(JVM、GC)和其Web服务程序有所了解。
以下是Java自带的性能监控工具
jps(jps -mlvV) | 与Linux上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号。 |
jstat(man jstat | jstat -gc $jpid) | 监视VM内存工具,可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。 |
jmap(Memory Map |jmap -heap $jpid) | 打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。 |
jstack(Linux特有| jstack -l $jpid) | 观察jvm中当前所有线程的运行情况和线程当前状态。 |
jinfo(Linux特有| jinfo $jpid) | 运行中的java程序的运行环境参数,参数包括Java System属性和JVM命令行参数 |
jconsole | 结合上述功能的GUI工具,监控到:CPU、内存、线程数、类数量,展现VM摘要、Mbean集属性。 |
jvisualvm | Java5之后内置的监控工具,和Jconsole相似,Dump功能强大!并有Profile功能。 |
jhat | 用于解析Java的Dump文件,并启动Web服务供浏览。 |
必要时我们需要抓取Java全内存的Dump来分析,抓取方式有如下:
jmap -dump <options> |
jvm中添加参数:-XX:+HeapDumpOnOutOfMemoryError 在符合条件时会输出Dump。 |
hprof输出:java -agentlib:hprof[=options] ToBeProfiledClass | java -agentlib:hprof=help |
jvisualvm:有界面,可生成各种镜像和Dump。 |
那么Dump怎样分析呢?
jhat | 用于解析Java的Dump文件,并启动Web服务供浏览。 |
mat(Memory Analyzer) | 开源分析工具,可形成报告。官网:http://www.eclipse.org/mat/ |
JDK还内置了一些演示程序供参考,给被监控程序添加启动参数后执行以下指令:
java -jar $JAVA_HOME/demo/management/MemoryMonitor/MemoryMonitor.jar 192.168.223.108:8950 |
java -jar $JAVA_HOME/demo/management/FullThreadDump/FullThreadDump.jar 192.168.223.108:8950 |
java -jar $JAVA_HOME/demo/management/JTop/JTop.jar 192.168.223.108:8950 |
java -jar $JAVA_HOME/demo/management/VerboseGC/VerboseGC.jar 192.168.223.108:8950 |
OK,由于篇幅限制,接下来介绍一下商业监控工具吧:
Jprofiler | http://www.ej-technologies.com/ |
JRockit | http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html |
Yourkit | http://www.yourkit.com |
Jprofiler专门针对Java性能监控设计。
JRockit则是一套JVM,有其配套的监控系统和工具。
Yourkit没用过,出品了java和.net的监控。
废话不多说,下面我来演示一下如何Jprofile来定位Java的性能问题。以Jboss为例:
在/usr/local/jboss/bin/run.conf里添加JAVA_OPTS:`-agentpath:libjprofilerti.so=port=8849`,启动Jboss。
这里我做了示例程序,在此理解为某产品的三个版本。访问方式如下:
http://TestServer/Servlet/Demo?Version=1
http://TestServer/Servlet/Demo?Version=2
http://TestServer/Servlet/Demo?Version=3
性能体现如下:
v1:正常,性能好且表现稳定(点击率曲线平稳在6600)
v2:性能下降明显(点击率曲线平稳在2800),需要尽快找出原因
v3:程序不稳定,运行越来越慢(刚启动是点击率约4200,随后渐跌至0),久了就宕机(后台抛内存溢出)
使用Jprofile监控,问题轻松被定位。如下图:
1、“CPU Views”部分为进行v2的测试过程截图。问题定位在加解密上,即这块需要优化。
2、“Heap Walker”部分为进行v3的测试过程截图。问题定位在Session处理上,说明Session机制需要调整。
上述示例的代码也贴出来了,AES加密代码较多未贴需要读者自己实现了:
public class Demo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
String version = request.getParameter("Version");
response.setContentType("text/html ;charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
PrintWriter out = response.getWriter();
String result = new String();
String rand = UUID.randomUUID().toString();
if(version==null) version = "0";
switch(Integer.parseInt(version)){
case 1:
result = "Version1:" + ClacMD5(rand);
break;
case 2:
result = "Version2:" + ClacAES(rand);
break;
case 3:
result = "Version3:" + MakeSession(request,rand);
break;
default:
result = "Default:" + "Hello higkoo !";
break;
}
out.write(result);
out.close();
}
public String ClacMD5(String str){
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(str.getBytes("utf-8"));
StringBuffer sb =new StringBuffer();
String result = new String();
if(str !=null){
for(int i =0; i < array.length; i++){
sb.append(Integer.toHexString((array[i]&0xFF)|0x100).toUpperCase().substring(1,3));
}
result = sb.toString();
}
return result;
}
public String ClacAES(String str){
String kStr = "866563b712d204d82876d1153d06c1f11";
String result = new String();
String eStr = AESUtil.encrypt(AESUtil.encrypt(AESUtil.encrypt(str.replaceAll("-", ""), kStr),kStr),kStr);
result = AESUtil.decrypt(AESUtil.decrypt(AESUtil.decrypt(eStr, kStr),kStr),kStr);
return result.toUpperCase();
}
public String MakeSession(HttpServletRequest request,String str) {
HttpSession session=request.getSession(true);
session.setAttribute("accessCount", str);
return session.getId() ;
}
}