JDK版本:8

背景

做为一名写了几年CRUD的java程序猿,想要突破瓶颈,实现摆脱业务的目标理想,JVM是门必修课,也是块敲门砖。JVM的理论知识非常抽象且枯燥,很多人还没入门就放弃了。因此笔者推荐从以下三个点作为入口,降低入门难度,学会使用现有工具,直观地去了解JVM:

  • 学会查看JVM字节码指令
  • 学会查看JVM运行时数据区变化
  • 学会查看.class文件在JVM中的存储形式(也可以说是:类的元信息在JVM中的存储形式)

查看JVM字节码指令:IDEA插件jclasslib

  1. 菜单栏 -> File -> Settings -> Plugins -> 搜索jclasslib -> 安装完成后重启IDEA(图一)
  2. 选中任意.java文件 -> 菜单栏 -> View -> Show Bytecode With Jclasslib
  3. 右侧展示该类编译成JVM字节码指令的信息(图二)

注意:.java文件修改后,需要先build,然后点击jclasslib中的Reload,才能看到最新的信息

使用java工具查看jvm 如何查看jvm_菜单栏


使用java工具查看jvm 如何查看jvm_菜单栏_02

查看JVM运行时数据区变化:JDK自带jvisualvm

  1. 坐标:C:\Program Files\Java\jdk1.8.0_211\bin\jvisualvm.exe 双击打开
  2. 本地起一个java应用,然后jvisualvm左边应用程序中找到对应的java应用,双击加载
  3. 监视页查看JVM运行时数据区

使用java工具查看jvm 如何查看jvm_菜单栏_03

Visual GC插件

jvisualvm自带的监视页对堆内存变化的收集粒度太大,这里可以借助Visual GC插件:

  1. 菜单栏 -> 工具 -> 插件 -> 搜索Visual GC -> 安装完成后重启jvisualvm(图一)
  2. 重启后加载应用,会多出一个Visual GC的tab页(图二)

使用java工具查看jvm 如何查看jvm_JVM_04


使用java工具查看jvm 如何查看jvm_jvm_05

查看.class文件在JVM中的存储形式:JDK自带HSDB

  1. 坐标:C:\Program Files\Java\jdk1.8.0_211\lib
  2. 打开shell输入:java -cp .\sa-jdi.jar sun.jvm.hotspot.HSDB(shell不能关闭)
  3. 本地起一个java应用,使用 jps -l 命令查看进程ID
  4. HSDB 菜单栏 -> File -> Attack to HotSpot process
  5. 输入进程ID,点击OK

第一次加载shell可能会报错:大致内容就是找不到sawindbg.dll文件

Exception in thread "Thread-1" java.lang.UnsatisfiedLinkError: Can't load library: C:\Program Files\Java\jre1.8.0_211\bin\sawindbg.dll
        at java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.lang.Runtime.load0(Unknown Source)
        ...

这个文件在C:\Program Files\Java\jdk1.8.0_211\jre\bin,找到他并拷贝到C:\Program Files\Java\jre1.8.0_211\bin即可,再次执行步骤五:

使用java工具查看jvm 如何查看jvm_使用java工具查看jvm_06


菜单栏 -> Tools -> Class Browser 查看JVM加载的所有Klass信息(图一)

输入类名快速定位,找到对应的Klass对象,点击查看详情,这里可以看到JVM字节码指令(图二)

使用java工具查看jvm 如何查看jvm_菜单栏_07


使用java工具查看jvm 如何查看jvm_JVM_08


"@“符号后面的字符串就是该Klass对象的内存地址,复制内存地址

菜单栏 -> Tools -> Inspector 输入内存地址,回车,可以看到Klass对象在内存中的存储形式

使用java工具查看jvm 如何查看jvm_JVM_09


使用Debug启动的java应用,在Stop之前要先在HSDB中Detach,否则java应用结束不了

如同spring中的BeanDifination,spring可以通过BeanDifination创建出Bean;.class文件在内存中的存在形式也是一个对象(demo中是InstanceKlass类型的对象),在使用到该类型时,JVM通过该对象进行初始化,镜像出该类型的实例,存放在堆区,也就是我们常说的引用类型"对象”。