JVM | 使用 HSDB 探秘运行时数据区

本贴最后更新于 1539 天前,其中的信息可能已经事过境迁

开头说两句

Java 基础 Demo 站: https://www.javastudy.cloud
Java 中高级开发博客: https://www.lixiang.red
Java 学习公众号: Java 技术大本营

本文知识点

  • HSDB 的使用
  • HSDB 查看栈信息
  • HSDB 查看堆信息
  • Class 对象,static 对象,Klass 的关系
  • 需要注意, 本文所用 JDK 环境为 JDK11,网上有很多博客是基于 JDK1.7, 两者的方法区的实现不一样,所以有些数据展示也会不同。

运行代码

public class Main {

    static class TestObject{
        public void testOut(){
            System.out.println("java技术大本营");
            System.out.println("break");
        }

    }

    /** 类静态变量, 这个也在堆中, 在Class对象中 */
    private static TestObject staticObject = new TestObject();

    /** 类变量,这个应该在堆中 */
    private TestObject classObject  = new TestObject();

    public static void main(String[] args) {

        Main main = new Main();
        // 方法内对象,应该在堆中
        TestObject innerObject  = new TestObject();
        innerObject.testOut();

    }
}

HSDB 的使用

HSDB 全称是 HotSpotDebugger, HotSpot 虚拟机的调试工具,在使用的时候,需要程序处在暂停的状态,可以直接使用 Idea 的 debug 工具。 使用 HSDB 可以看到堆栈里面相关的内容,

启动 HSDB

无论哪种方式启动,都需要先知道当前 Java 程序的进程号,我们使用 jps 命令,如下图所示:

然后我们使用命令 jhsdb hsdb --pid=87854 来启动 HSDB,如下图所示:

image.png

使用 HSDB 查看 JVM 虚拟机栈信息

我们知道,在创建一个线程时,都会有一个为之分配一个 jvm 栈,如上图我们可以看到在 Java Threads 中有 5 个线程,我们选中 main 线程,然后点击上面的查看栈信息的图标,如下图所示:

image.png

1:在原 Java Threads 面板上,点第二个按钮,可召唤出 Stack Memory for main 这个面板。

Stack Memory for main 面板主体有三大部分,如上图所述

2:最左侧是栈的内存地址

3:中间一列是该地址上存的值(大多是别的对象的地址),

4:最右侧是 HotSpot 的说明

5:在右侧的说明中, 我们可以此时栈中有两个栈帧(Frame)

大家看到 Young com/platform/tools/jvm/Main$TestObject 这个我们定义的对象,记住这个地址 0x00000001161d11e0 代表这个对象是在栈中被引用

使用 HSDB 查看堆信息

我们的对象大都是在堆里面,我们可以借助 HSDB 看堆中有多少个实例对象,如下图所示

image.png

1:点击 Tools->Object Histogram ,打开右边的 Object Histogram 面板

2:在 2 处输入我们的类全名,然后点 3 望远镜搜索,在下面会显示 我们的类,有三个实例

4:可以双击选中我们的类, 也可以放大镜,可以打开 Show Objects of Type 面板 看到三个实例的详情

其中第三个,就是我们在栈中看到的方法内的成员变量。

对于另外两个,需要通过反向指针查询 ,看哪个类引用了这个实例,来看是哪个变量

HSDB 使用 revptrs 看实例引用

对于上面还有两个地址, 我们不能确定是什么对象,所以我们可以通过指针反查来看他们被什么所引用,如下图所示:

image.png

如上图,我们可以看到,一个被 Class 对象所引用, 是类静态变量,一个被 jvm/Main , 也就是我们 Main 类引用, 是类成员变量。 通过这个我们也可以总结, 静态变量,其实也是存在堆里面。

Class,static 及 Klass 的关系

这个版本的 hsdb 有些指令不支持,如 mem , whatis 等,所以要深入学习的小伙伴可以用 jdk1.8 的 hsdb 试下上述两个命令

多个 Java 对象(Java Object,在堆中)对应同一个 Klass(在 MetaSpace 中)对应同一个 Class 对象(在堆中), 类的静态变量地址都存在 Class 对象的后面(所以也在堆中).

总结

运行时数据区和 HSDB 结合起来一起学习,可以更好的看到虚拟机内部的状态,有一些很初次接触的概念点,如 Klass , Class 对象,先弄懂其关联关系,存放在哪里, 再去深入研究其代码。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3167 引用 • 8207 回帖 • 1 关注
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 2 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...