JDK版本:8
背景
做为一名写了几年CRUD的java程序猿,想要突破瓶颈,实现摆脱业务的目标理想,JVM是门必修课,也是块敲门砖。JVM的理论知识非常抽象且枯燥,很多人还没入门就放弃了。因此笔者推荐从以下三个点作为入口,降低入门难度,学会使用现有工具,直观地去了解JVM:
- 学会查看JVM字节码指令
- 学会查看JVM运行时数据区变化
- 学会查看.class文件在JVM中的存储形式(也可以说是:类的元信息在JVM中的存储形式)
查看JVM字节码指令:IDEA插件jclasslib
- 菜单栏 -> File -> Settings -> Plugins -> 搜索jclasslib -> 安装完成后重启IDEA(图一)
- 选中任意.java文件 -> 菜单栏 -> View -> Show Bytecode With Jclasslib
- 右侧展示该类编译成JVM字节码指令的信息(图二)
注意:.java文件修改后,需要先build,然后点击jclasslib中的Reload,才能看到最新的信息
查看JVM运行时数据区变化:JDK自带jvisualvm
- 坐标:C:\Program Files\Java\jdk1.8.0_211\bin\jvisualvm.exe 双击打开
- 本地起一个java应用,然后jvisualvm左边应用程序中找到对应的java应用,双击加载
- 监视页查看JVM运行时数据区
Visual GC插件
jvisualvm自带的监视页对堆内存变化的收集粒度太大,这里可以借助Visual GC插件:
- 菜单栏 -> 工具 -> 插件 -> 搜索Visual GC -> 安装完成后重启jvisualvm(图一)
- 重启后加载应用,会多出一个Visual GC的tab页(图二)
查看.class文件在JVM中的存储形式:JDK自带HSDB
- 坐标:C:\Program Files\Java\jdk1.8.0_211\lib
- 打开shell输入:java -cp .\sa-jdi.jar sun.jvm.hotspot.HSDB(shell不能关闭)
- 本地起一个java应用,使用 jps -l 命令查看进程ID
- HSDB 菜单栏 -> File -> Attack to HotSpot process
- 输入进程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即可,再次执行步骤五:
菜单栏 -> Tools -> Class Browser 查看JVM加载的所有Klass信息(图一)
输入类名快速定位,找到对应的Klass对象,点击查看详情,这里可以看到JVM字节码指令(图二)
"@“符号后面的字符串就是该Klass对象的内存地址,复制内存地址
菜单栏 -> Tools -> Inspector 输入内存地址,回车,可以看到Klass对象在内存中的存储形式
使用Debug启动的java应用,在Stop之前要先在HSDB中Detach,否则java应用结束不了
如同spring中的BeanDifination,spring可以通过BeanDifination创建出Bean;.class文件在内存中的存在形式也是一个对象(demo中是InstanceKlass类型的对象),在使用到该类型时,JVM通过该对象进行初始化,镜像出该类型的实例,存放在堆区,也就是我们常说的引用类型"对象”。