jvm三之虚拟机性能监控以及故障处理

给一个系统定位问题的时候,知识、经验是关键基础,数据是依据,工具是运用知识处理数据的手段

在这里插入图片描述
具体功能都在tools.jar中
**加粗样式**
在这里插入图片描述

命令行工具

在这里插入图片描述

jps(JVM process Status Tool)

虚拟机进程状况工具
		列出正在运行的虚拟机进程,
		显示虚拟机执行主类(Main Class,main()函数所在类)的名称,
		进程在本地虚拟机的唯一ID(LVMID local Virtual Machine Identifier)
		通过RMI协议查询开启RMI服务的远程虚拟机进程状态
		LVMID与操作系统的进程id(PID,Process Identifier)一致

在这里插入图片描述
在这里插入图片描述

jps失效问题

java程序启动后,会在目录/tmp/hsperfdata_{userName}/下生成几个文件,文件名就是java进程的pid,因此jps列出进程id就是把这个目录下的文件名列一下而已,至于系统参数,则是读取文件中的内容。

我们来思考下:如果由于磁盘满了,无法创建这些文件,或者用户对这些文件没哟读的权限。又或者因为某种原因这些文件或者目录被清除,出现以上这些情况,就会导致jps命令失效。

如果jps命令失效,而我们又要获取pid,还可以使用以下两种方法:

1、top | grep java
2、ps -ef |grep java

jstat(JVM statistics Monitoring Tool)

监视虚拟机各种运行状态信息工具
	显示本地或远程虚拟机进程中的类装载,内存,垃圾收集,JIT编译等运行数据
命令格式
jstat[option vimd [interval[s|ms][count]]]
本地虚拟机进程vmid和lvmid一致
远程虚拟机进程,vmid格式为[protocol:][//]lvmid[@hostname[:port]/servername]
interval与count表示:查询间隔和次数,省略默认查询一次
opt:用户希望查询的虚拟机信息,类装载,垃圾收集,运行期编译状况

在这里插入图片描述
在这里插入图片描述
S0和S1表示2个Survivor区
O:老年代
P:永久代
YGC:新生代GC次数
FGC:full GC次数
FGCT:full GC总耗时
GCT:GC总耗时

jinfo

java配置信息工具
实时查看和调整虚拟机的各项参数
jps -v:查看虚拟机启动时显示指定的参数列表
-flag:未被显式指定的参数的系统默认值(1.6及以上,使用java -XX:+PrintFlagsFinal也可以)
-sysprops:打印虚拟机进程的System.getProperties()
JDK1.6之后:-flag [+|-]name或者 -flag name=value修改一部分运行期间可写的虚拟机参数值
命令
jinfo [option] pid

在这里插入图片描述

在这里插入图片描述

jmap

java内存映像工具
用于生成堆转换快照(一般称之为heapdump/dump文件),查询finalize执行队列,java堆和永久代的详细信息(如空间使用率,当前用的是那种收集器等)
也可以使用-XX:+HeapDumpOnOutOfMemoryError参数:虚拟机在OOM异常出现之后自动生成dump文件
-XX:+HeapDumpOnCtrlBreak:可以使用Ctrl+Break键让虚拟机生成dump文件,
Linux可以使用Kill -3发出进程退出信号,生成dump文件
-dump/-histo只能在window使用,其余选项,只能在linux/solaris使用
命令格式
jmap [option] vmid

在这里插入图片描述

jmap -dump:format=b,file=a 7664

在这里插入图片描述

jhat

分析jmap生成的堆转储快照
内置卫星的HTTP/HTML服务器,生成的dump文件分析结果后可以在浏览器中查看,分析结果默认包单位分组
http://localhost:7000/
局限,分析耗时且消耗硬件资源,功能过于简陋
命令格式
jhat dump文件路径

在这里插入图片描述
在这里插入图片描述

OQL

类似于SQL的查询语言,用于查询Java堆。
在这里插入图片描述
在这里插入图片描述

jstack

java堆栈跟踪工具
生成虚拟机当前时刻的线程快照(一般称之为threaddump/javacore文件)
线程快照就是当前虚拟机内每一条线程正在执行的堆栈的集合
线程快照主要目的定位线程出现长时间停顿的原因(如线程间死锁,死循环..)
命令格式
jstack [option] vmid
java.lang.Thread#getAllStackTraces()用于获取虚拟机中所有线程的StackTraceElement对象,可以完成jstack大部分功能

在这里插入图片描述

在这里插入图片描述

可视化工具

jhsdb

在这里插入图片描述

/**
 * -Xmx10m -XX:+UseSerialGC -XX:-UseCompressedOops
 * 由于JHSDB本身对压缩指针的支持存在很多缺陷,建议用64位系统的读者在实验时禁用压缩指针(-XX:-UseCompressedOops)
 */
public class JHSDB_TestCase {
    static class Test {
        static ObjectHolder staticObj = new ObjectHolder();//方法区,元空间,对象存储堆中
        ObjectHolder instanceObj = new ObjectHolder();   //堆中

        void foo() {
            ObjectHolder localObj = new ObjectHolder();//foo局部变量表栈中存索引,对象存储堆中
            System.out.println("done"); // 这里设一个断点
        }

    }
    private static class ObjectHolder {
    }
    public static void main(String[] args) {
        Test test = new JHSDB_TestCase.Test();
        test.foo();
    }
}

在java9之前,JAVA_HOME/lib目录下有个sa-jdi.jar,可以通过如上命令启动HSDB(图形界面)及CLHSDB(命令行)
sa-jdi.jar中的sa的全称为Serviceability Agent,它之前是sun公司提供的一个用于协助调试HotSpot的组件,而HSDB便是使用Serviceability Agent来实现的
HSDB就是HotSpot Debugger的简称,由于Serviceability Agent在使用的时候会先attach进程,然后暂停进程进行snapshot,最后deattach进程(进程恢复运行),所以在使用HSDB时要注意

启动图形页面
java -cp $JAVA_HOME/lib/sa-jdi.jar sun.jvm.hotspot.HSDB 
启动命令行
java -cp $JAVA_HOME/lib/sa-jdi.jar sun.jvm.hotspot.CLHSDB		

在这里插入图片描述

在这里插入图片描述
使用scanoops命令在Java堆的新生代(从Eden起始地址到To Survivor结束地址)范围内查找ObjectHolder的实例

命令行:scanoops 0x04a00000 0x04f50000 C_JConsoleAndVisualVM.JHSDB_TestCase$ObjectHolder

在这里插入图片描述
发现有三个ObjectHolder对象,三个对象分别存储在堆中,
staticObj,instanceObj存储堆中,localObj存储局部变量表(栈中)

通过Inspector查看存放对象信息
可以查看到对象头和指向对象元数据的指针,里面包括了Java类型的名字、继承关系、实现接口关系,字段信息、方法信息、运行时常量池的指针、内嵌的虚方法表(vtable)以及接口方法表(itable)等。
在这里插入图片描述

revptrs 0x04c1fd50 0x04c1d1c0
revptrs 0x04c1fd68 0x04c1fd58
revptrs 0x04c1fd70
在这里插入图片描述
可以看到0x04c1fd50由0x04c1d1c0引用
下图也看得出来
在这里插入图片描述
在这里插入图片描述
当查看0x04c1fd70引用的时候发现null,也就是说不在堆中,刚测的2个在堆中的对象分别是staticObj,instanceObj,也就是说localObj的引用不在堆,它的引用在局部变量表栈中,从栈中查找就行了
在这里插入图片描述
jdk8这里显示的是局部变量没有找到引用,无法测试了,正常的显示应该是在
在这里插入图片描述

jconsole

在这里插入图片描述

在这里插入图片描述

空循环

可看见线程处于RUNNABLE运行状态,这种情况会一直占用CPU
在这里插入图片描述

活锁

在这里插入图片描述

死锁

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

jvisualvm

插件下载

点击工具->插件
在这里插入图片描述
下载插件会jdk1.6\lib\visualvm放在此目录下

生成堆快照

在这里插入图片描述

保存以及导入
dump文件保存,创建dump文件后,右键-->另存为,不这样的话关闭visualVM时默认当做临时文件处理掉
导入:点击window视图-->文件-->装入-->选择文件

分析CPU和内存

在这里插入图片描述
注意:jdk1.5之后,在client模式下的虚拟机加入并且自动开启了类共享,这是一个在多虚拟机进程中共享rt.jar中的类数据以提高加载速度和节省内存的优化
VisualVM的Profiler功能可能会因为类共享而导致被监视的应用程序崩溃,建立关闭类共享优化-Xshare:off

BTrace动态日志跟踪

在不停止目标程序运行的前提下,通过HotSpot虚拟机的HotSwap技术动态加入原本并不存在的调试代码。
范围使用:排除错误,如方法参数,返回值
1:下载BTrace插件
2: 点击应用程序面板右键,点击Trace Application
在这里插入图片描述

在这里插入图片描述

代码清单

public class D_testVisualVM {
	public int add(int a, int b) {
		return a + b;
	}

	public static void main(String[] args) throws Exception {
		D_testVisualVM b_Trace = new D_testVisualVM();
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		for (int i = 0; i < 10; i++) {
			br.readLine();
			int a = (int) (Math.random() * 1000);
			int b = (int) (Math.random() * 1000);
			System.out.println(b_Trace.add(a, b));
		}
	}
}

日志代码

 import com.sun.btrace.annotations.*;  
import static com.sun.btrace.BTraceUtils.*;  
@BTrace  
public class TracingScript {  
   @OnMethod(  
      clazz="C_JConsoleAndVisualVM.D_testVisualVM",  
      method="add",  
      location=@Location(Kind.RETURN)  
   )  
   public static void func(@Self C_JConsoleAndVisualVM.D_testVisualVM instance,int a,int b ,@Return int result){  
 
    jstack();
    println(strcat("方法参数A:",str(a)));
        println(strcat("方法参数B:",str(b)));
            println(strcat("方法结果:",str(result)));
   }  
}  

在运行期间动态织入日志代码,跟idea,debug时可以动态设置步入条件语句,还有Fiddler抓websocket织入语句一样.

JMC

Java Mission Control:可持续在线的监控工具

在这里插入图片描述
JFR的基本工作逻辑是开启一系列事件的录制动作,当某个事件发生时,这个事件的所有上下文
数据将会以循环日志的形式被保存至内存或者指定的某个文件当中,循环日志相当于数据流被保留在
一个环形缓存中,所以只有最近发生的事件的数据才是可用的。JMC从虚拟机内存或者文件中读取并
展示这些事件数据,并通过这些数据进行性能分析。

HotSpot虚拟机插件及工具

·Ideal Graph Visualizer:用于可视化展示C2即时编译器是如何将字节码转化为理想图,然后转化为
机器码的。
·Client Compiler Visualizer[1]:用于查看C1即时编译器生成高级中间表示(HIR),转换成低级中
间表示(LIR)和做物理寄存器分配的过程。
·MakeDeps:帮助处理HotSpot的编译依赖的工具。
·Project Creator:帮忙生成Visual Studio的.project文件的工具。
·LogCompilation:将-XX:+LogCompilation输出的日志整理成更容易阅读的格式的工具。
·HSDIS:即时编译器的反汇编插件。

HSDIS:JIT生成代码反汇编

让HotSpot的-XX:+PrintAssembly指令调用它来把即时编译器动态生成的本
地代码还原为汇编代码输出,同时还会自动产生大量非常有价值的注释

使用的是SlowDebug或者FastDebug版的HotSpot,那可以直接通
过-XX:+PrintAssembly指令使用的插件;如果使用的是Product版的HotSpot,则还要额外加入一
个-XX:+UnlockDiagnosticVMOptions参数才可以工作

命令
java -XX:+PrintAssembly -Xcomp -XX:CompileCommand=dontinline,*Bar.sum -XX:Compile-Command=compileonly,*Ba
参数-Xcomp是让虚拟机以编译模式执行代码,这样不需要执行足够次数来预热就能触发即
时编译。两个-XX:CompileCommand的意思是让编译器不要内联sum()并且只编译sum(),-XX:
+PrintAssembly就是输出反汇编内容

当汇编代码量过大的时候,可使用JITWatch

java -XX:+PrintAssembly -XX:+UnlockDiagnosticVMOptions -Xcomp -XX:CompileCommand=dontinline,*Bar.sum -XX:Compile-Command=compileonly,*B

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值