JVM系列学习(二):基于JVisualVM的可视化监控

基于JVisualVM的可视化监控

监控本地Tomcat

  1. 路径:\Java\jdk1.8.0_171\bin\jvisualvm.exe
  2. 打开之后更新插件 地址

在这里插入图片描述

监控远程Tomcat

  1. 修改Catalina.sh

    JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=port -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=ip地址"
  2. jar包启动添加参数

    nohup java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=port -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=ip地址 -jar XXXX.jar &
  3. VisualVM官方英文文档

  4. VisualVM优秀的中文文档指南

基于Btrace的监控调试

Btrace安装入门

  1. Btrace可以动态地向目标应用程序地字节码注入追踪代码

  2. 安装github地址

  3. 设置环境变量

    • jps -l
    • btrace pid 类名.java
  4. package com.imooc.monitor_tuning.chapter4;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.imooc.monitor_tuning.chapter2.User;
    
    @RestController
    @RequestMapping("/ch4")
    public class Ch4Controller {
    	
    	@RequestMapping("/arg1")
    	public String arg1(@RequestParam("name")String name) {
    		return "hello,"+name;
    	}
    	
    	@RequestMapping("/arg2")
    	public User arg2(User user) {
    		return user;
    	}
    	
    	@RequestMapping("/constructor")
    	public User constructor(User user) {
    		return user;
    	}
    	
    	@RequestMapping("/same1")
    	public String same(@RequestParam("name")String name) {
    		return "hello,"+name;
    	}
    	@RequestMapping("/same2")
    	public String same(@RequestParam("name")String name,@RequestParam("id")int id) {
    		return "hello,"+name+","+id;
    	}
    	
    	@RequestMapping("/exception")
    	public String exception() {
    		try {
    			System.out.println("start...");
    			System.out.println(1/0);
    			System.out.println("end...");
    		}catch(Exception e) {
    			//
    		}
    		return "success";
    	}
    
    }

Btrace使用详解

拦截方法

  1. 普通方法:@OnMethod(clazz="",method="")

    package com.imooc.monitor_tuning.chapter4;
    import com.sun.btrace.AnyType;
    import com.sun.btrace.BTraceUtils;
    import com.sun.btrace.annotations.BTrace;
    import com.sun.btrace.annotations.Kind;
    import com.sun.btrace.annotations.Location;
    import com.sun.btrace.annotations.OnMethod;
    import com.sun.btrace.annotations.ProbeClassName;
    import com.sun.btrace.annotations.ProbeMethodName;
    
    @BTrace
    public class PrintArgSimple {
    	
    	@OnMethod(
    	        clazz="com.imooc.monitor_tuning.chapter4.Ch4Controller",
    	        method="arg1",
    	        location=@Location(Kind.ENTRY)
    	)
    	public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
    		BTraceUtils.printArray(args);
    		BTraceUtils.println(pcn+","+pmn);
    		BTraceUtils.println();
        }
    }
  2. 构造方法:@OnMethod(clazz="",method="")

    package com.imooc.monitor_tuning.chapter4;
    import com.sun.btrace.AnyType;
    import com.sun.btrace.BTraceUtils;
    import com.sun.btrace.annotations.BTrace;
    import com.sun.btrace.annotations.OnMethod;
    import com.sun.btrace.annotations.ProbeClassName;
    import com.sun.btrace.annotations.ProbeMethodName;
    
    @BTrace
    public class PrintConstructor {
    	
    	@OnMethod(
    	        clazz="com.imooc.monitor_tuning.chapter2.User",
    	        method="<init>"
    	)
    	public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
    		BTraceUtils.println(pcn+","+pmn);
    		BTraceUtils.printArray(args);
    		BTraceUtils.println();
        }
    }
  3. 同名方法:用参数类型来区分

    package com.imooc.monitor_tuning.chapter4;
    import com.sun.btrace.BTraceUtils;
    import com.sun.btrace.annotations.BTrace;
    import com.sun.btrace.annotations.OnMethod;
    import com.sun.btrace.annotations.ProbeClassName;
    import com.sun.btrace.annotations.ProbeMethodName;
    
    @BTrace
    public class PrintSame {
    	
    	@OnMethod(
    	        clazz="com.imooc.monitor_tuning.chapter4.Ch4Controller", //具体到类
    	        method="same"//具体到类中的方法
    	)
    	public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name) {
    		BTraceUtils.println(pcn+","+pmn + "," + name);
    		BTraceUtils.println();
        }
        //或者
        	public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name,int id) {//拦截有String,int参数类型的same方法
    		BTraceUtils.println(pcn+","+pmn + "," + name);
    		BTraceUtils.println();
        }
    }

拦截时机

  1. 入口,默认值:Kind.ENTRY

  2. 返回:Kind.RETURN

    package com.imooc.monitor_tuning.chapter4;
    import com.sun.btrace.AnyType;
    import com.sun.btrace.BTraceUtils;
    import com.sun.btrace.annotations.BTrace;
    import com.sun.btrace.annotations.Kind;
    import com.sun.btrace.annotations.Location;
    import com.sun.btrace.annotations.OnMethod;
    import com.sun.btrace.annotations.ProbeClassName;
    import com.sun.btrace.annotations.ProbeMethodName;
    import com.sun.btrace.annotations.Return;
    
    @BTrace
    public class PrintReturn {
    	
    	@OnMethod(
    	        clazz="com.imooc.monitor_tuning.chapter4.Ch4Controller",
    	        method="arg1",
    	        location=@Location(Kind.RETURN)
    	)
    	public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, @Return AnyType result) {
    		BTraceUtils.println(pcn+","+pmn + "," + result);
    		BTraceUtils.println();
        }
    }
  3. 异常:Kind.THROW

    /* * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the Classpath exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */
    
    package com.imooc.monitor_tuning.chapter4;
    
    import com.sun.btrace.BTraceUtils;
    import com.sun.btrace.annotations.BTrace;
    import com.sun.btrace.annotations.Kind;
    import com.sun.btrace.annotations.Location;
    import com.sun.btrace.annotations.OnMethod;
    import com.sun.btrace.annotations.Self;
    import com.sun.btrace.annotations.TLS;
    
    @BTrace 
    public class PrintOnThrow {    
        // store current exception in a thread local
        // variable (@TLS annotation). Note that we can't
        // store it in a global variable!
        @TLS 
        static Throwable currentException;
    
        // introduce probe into every constructor of java.lang.Throwable
        // class and store "this" in the thread local variable.
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>"
        )
        public static void onthrow(@Self Throwable self) {//拦截new Throwable()
            currentException = self;
        }
    
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>"
        )
        public static void onthrow1(@Self Throwable self, String s) {//拦截new Throwable(String msg)
            currentException = self;
        }
    
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>"
        )
        public static void onthrow1(@Self Throwable self, String s, Throwable cause) {//拦截new Throwable(String msg, Throwable cause)
            currentException = self;
        }
    
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>"
        )
        public static void onthrow2(@Self Throwable self, Throwable cause) {//拦截new Throwable(Throwable cause)
            currentException = self;
        }
    
        // when any constructor of java.lang.Throwable returns
        // print the currentException's stack trace.
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>",
            location=@Location(Kind.RETURN)
        )
        public static void onthrowreturn() {
            if (currentException != null) {
            	BTraceUtils.Threads.jstack(currentException);
            	BTraceUtils.println("=====================");
                currentException = null;
            }
        }
    }
  4. 行:Kind.LINE 可以定位问题

    package com.imooc.monitor_tuning.chapter4;
    import com.sun.btrace.BTraceUtils;
    import com.sun.btrace.annotations.BTrace;
    import com.sun.btrace.annotations.Kind;
    import com.sun.btrace.annotations.Location;
    import com.sun.btrace.annotations.OnMethod;
    import com.sun.btrace.annotations.ProbeClassName;
    import com.sun.btrace.annotations.ProbeMethodName;
    
    @BTrace
    public class PrintLine {
    	
    	@OnMethod(
    	        clazz="com.imooc.monitor_tuning.chapter4.Ch4Controller",
    	        method="exception",
    	        [email protected](value=Kind.LINE, line=XX)
    	)
    	public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, int line) {
    		BTraceUtils.println(pcn+","+pmn + "," +line);
    		BTraceUtils.println();
        }
    }

拦截this,参数,返回值

  1. this:@Self 异常中有举例
  2. 入参:可以用AnyType,也可以用真实类型,同名的用真实类型
  3. 返回:@Return
获取对象的值
  1. 简单类型:直接获取

  2. 复杂类型:反射,类名+属性名

    package com.imooc.monitor_tuning.chapter4;
    import java.lang.reflect.Field;
    
    import com.imooc.monitor_tuning.chapter2.User;
    import com.sun.btrace.BTraceUtils;
    import com.sun.btrace.annotations.BTrace;
    import com.sun.btrace.annotations.Kind;
    import com.sun.btrace.annotations.Location;
    import com.sun.btrace.annotations.OnMethod;
    import com.sun.btrace.annotations.ProbeClassName;
    import com.sun.btrace.annotations.ProbeMethodName;
    
    @BTrace
    public class PrintArgComplex {
    	//btrace -cp "target/classes路径" pid 类名.java
    	@OnMethod(
    	        clazz="com.imooc.monitor_tuning.chapter4.Ch4Controller",
    	        method="arg2",
    	        location=@Location(Kind.ENTRY)
    	)
    	public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, User user) {
    		//print all fields
    		BTraceUtils.printFields(user);
    		//print one field
    		Field filed2 = BTraceUtils.field("com.imooc.monitor_tuning.chapter2.User", "name");
    		BTraceUtils.println(BTraceUtils.get(filed2, user));
    		BTraceUtils.println(pcn+","+pmn);
    		BTraceUtils.println();
        }
    }

拦截其他

  1. 正则表达式

    package com.imooc.monitor_tuning.chapter4;
    import com.sun.btrace.BTraceUtils;
    import com.sun.btrace.annotations.BTrace;
    import com.sun.btrace.annotations.OnMethod;
    import com.sun.btrace.annotations.ProbeClassName;
    import com.sun.btrace.annotations.ProbeMethodName;
    
    @BTrace
    public class PrintRegex {
    	
    	@OnMethod(
    	        clazz="com.imooc.monitor_tuning.chapter4.Ch4Controller",
    	        method="/.*/"
    	)
    	public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn) {
    		BTraceUtils.println(pcn+","+pmn);
    		BTraceUtils.println();
        }
    }
  2. 输出jinfo的参数

    package com.imooc.monitor_tuning.chapter4;
    
    import com.sun.btrace.BTraceUtils;
    import com.sun.btrace.annotations.BTrace;
    
    @BTrace
    public class PrintJinfo {
        static {
        	BTraceUtils.println("System Properties:");
        	BTraceUtils.printProperties();
        	BTraceUtils.println("VM Flags:");
        	BTraceUtils.printVmArguments();
        	BTraceUtils.println("OS Enviroment:");
        	BTraceUtils.printEnv();
        	BTraceUtils.exit(0);
        }
    }

注意事项

  1. 默认只能本地运行
  2. 生产环境下可以使用,但是被修改的字节码不会被还原