使用jhsdb查看JVM堆中对象的分配

总结一下运行<<深入理解Java 虚拟机>>书中的例子过程中遇到的问题。

环境准备

  • 安装JDK11
    JDK 11下载地址
    https://aws.amazon.com/cn/corretto/
    点击下载 Amazon Corretto 11使用jhsdb查看JVM堆中对象的分配_第1张图片
    根据各自的平台选择相应的JDK,我是在win10上安装,所以选择的是Windowsx64
    使用jhsdb查看JVM堆中对象的分配_第2张图片
    下载完成后安装,安装的过程比较简单,不会的可以自行去网上查。

  • 配置环境变量
    新建JAVA_HOME环境变量,路径为JDK11安装的根目录
    使用jhsdb查看JVM堆中对象的分配_第3张图片
    新建classpath环境变量,将路径设置为%JAVA_HOME%\lib
    使用jhsdb查看JVM堆中对象的分配_第4张图片

配置Path环境变量,新建一个环境变量将路径设置为%JAVA_HOME%\bin
使用jhsdb查看JVM堆中对象的分配_第5张图片

  • 编写测试代码
public class JHSDB_TestCase {
	static class Test {
		static ObjectHolder staticObj=new ObjectHolder();
		ObjectHolder instanceObj=new ObjectHolder();

		void foo() {
			ObjectHolder objectHolder=new ObjectHolder();
			System.out.println("done");
		}
	}

	private static class ObjectHolder {

	}

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

运行测试程序,使用jhsdb查看对象在堆中的分配

  • 调试模式运行
    配置JVM运行参数
    使用jhsdb查看JVM堆中对象的分配_第6张图片
    运行程序提示 “无效的源发行版11”
    使用jhsdb查看JVM堆中对象的分配_第7张图片
    修改Idea Project Structure中的Module SDK
    使用jhsdb查看JVM堆中对象的分配_第8张图片
    再次debug运行测试程序
    使用jhsdb查看JVM堆中对象的分配_第9张图片
  • 查看进程ID
运行 jps -l

使用jhsdb查看JVM堆中对象的分配_第10张图片

  • 使用jhsdb命令连接JVM进程
运行 jhsdb hsdb ---pid 23508 连接到JVM进程

提示不能确定我的JVM版本
使用jhsdb查看JVM堆中对象的分配_第11张图片

  • 查看JDK的版本
java -version

使用jhsdb查看JVM堆中对象的分配_第12张图片
因为的我的机器上安装了多个JDK,虽然配置的环境变量为JDK11,但是程序使用的是JDK8,JDK11的环境变量没有生效

解决办法

  • 查找java所在的目录
运行 where java

使用jhsdb查看JVM堆中对象的分配_第13张图片
从上图中可以看出java.exe文件有三个,将JDK11中的java.exe替换ProgramData\Oracle\Java\javapath目录下的java.exe
使用jhsdb查看JVM堆中对象的分配_第14张图片
使用jhsdb查看JVM堆中对象的分配_第15张图片

  • 运行jps 查看进程ID
    使用jhsdb查看JVM堆中对象的分配_第16张图片
  • 运行jhsdb
jhsdb hsdb --pid 28344

使用jhsdb查看JVM堆中对象的分配_第17张图片
JHSDB 界面
使用jhsdb查看JVM堆中对象的分配_第18张图片

  • 查看堆中的变量
    选择Tools->Heap Parameters,可以看到JVM堆新生代、老年代大小,已经使用的内存及内存地址的范围
    使用jhsdb查看JVM堆中对象的分配_第19张图片
  • 查找堆中的对象
    使用jhsdb查看JVM堆中对象的分配_第20张图片
  • 使用scanoops命令

使用jhsdb查看JVM堆中对象的分配_第21张图片

  • 输入地址的范围为eden起始地址到to surviver 结束地址 查找JHSDB_TestCase$ObjectHolder对象,提示类型不存在

使用jhsdb查看JVM堆中对象的分配_第22张图片

  • 输入全路径名称查找报错 sun.jvm.hotspot.debugger.DebuggerException: Windbg Error: ReadVirtual failed!
    使用jhsdb查看JVM堆中对象的分配_第23张图片
  • 使用scanoops 查询对象
scanoops 0x000001cb35a00000 0x000001cb35d00000 com/example/jvmdemo/jhsdb/JHSDB_TestCase$Test

提示报错 sun.jvm.hotspot.types.WrongTypeException: No suitable match for type of address 0x000001cb35b422c8
使用jhsdb查看JVM堆中对象的分配_第24张图片

  • 查看Main线程的方法调用栈
    使用jhsdb查看JVM堆中对象的分配_第25张图片
  • 从下图中可以看到ObjectHolder对象在新生代
    使用jhsdb查看JVM堆中对象的分配_第26张图片
    scanoops查找对象报错的问题还没找到原因,后续解决了再补上

参考
https://www.cnblogs.com/blog-zy/p/9364159.html
<<深入理解Java虚拟机>>

你可能感兴趣的:(Java虚拟机)