jvm内置性能监控与性能定位

阅读本文之前建立对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集属性。
jvisualvmJava5之后内置的监控工具,和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.jar192.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,由于篇幅限制,接下来介绍一下商业监控工具吧:

Jprofilerhttp://www.ej-technologies.com/
JRockithttp://www.oracle.com/technetwork/middleware/jrockit/overview/index.html
Yourkithttp://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加密代码较多未贴需要读者自己实现了:

package com.higkoo.tester;

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() ;
    }
}

原文:http://blog.csdn.net/ayan117/article/details/6832249
参考:http://blog.csdn.net/fenglibing/article/details/6411940

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值