30 借HSDB来探索HotSpot VM的运行时数据

Posted 蓝风9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了30 借HSDB来探索HotSpot VM的运行时数据相关的知识,希望对你有一定的参考价值。

前言

呵呵 R大的 经典文章 : 借HSDB来探索HotSpot VM的运行时数据 

也来 动手实际过一次 

另外就是 文章中提到的 根据 Method 查看方法的字节码信息, 这部分也还是挺有趣的, 我应该是 之前整理在 文档上面了的吧, 多久整理一下 

测试用例

package com.hx.test03;

/**
 * HSDBInspectClass
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2020-02-01 16:30
 */
public class Test16HSDBInspectClass 

  // static instanceClass & instanceClass
  private static InstanceClass staticInstance = new InstanceClass("staticInstance");
  private InstanceClass instance = new InstanceClass("instance");

//  三个 Test16HSDBInspectClass$InstanceClass 实例
//  0x000000079591fd38	Oop for com/hx/test03/Test16HSDBInspectClass$InstanceClass	InstanceKlass for com/hx/test03/Test16HSDBInspectClass$InstanceClass
//  0x000000079591fdb0	Oop for com/hx/test03/Test16HSDBInspectClass$InstanceClass	InstanceKlass for com/hx/test03/Test16HSDBInspectClass$InstanceClass
//  0x000000079591fdf8	Oop for com/hx/test03/Test16HSDBInspectClass$InstanceClass	InstanceKlass for com/hx/test03/Test16HSDBInspectClass$InstanceClass

  // Test16HSDBInspectClass
//  hsdb> revptrs 0x000000079591fd38
//  Computing reverse pointers...
//  Done.
//null
//  Oop for java/lang/Class @ 0x00000007959170d0
//  hsdb> revptrs 0x000000079591fdb0
//  Oop for com/hx/test03/Test16HSDBInspectClass @ 0x000000079591fda0
//  hsdb> revptrs 0x000000079591fdf8
//          null
//          null
//  hsdb>
  // 可以找到 静态变量 和 局部变量, revptrs 找不到 栈帧上面这一个
  // 但是可以从 main 方法的栈帧信息里面看到对应的 引用
//  hsdb> mem 0x000070000225f908
//          0x000070000225f908: 0x000000079591fdf8
  // 三个实例的三个引用, 一个在 instanceKlass 的 java_mirror 里面, 另外一个在新建的实例 thisInstance 里面, 一个在 栈帧上面
  public static void main(String[] args) 

    foo();

  

  // local instanceClass
  public static void foo() 
    Test16HSDBInspectClass thisInstance = new Test16HSDBInspectClass();
    InstanceClass localInstance = new InstanceClass("localInstance");
    System.out.println(" break point ");
  

  /**
   * InstanceClass
   *
   * @author Jerry.X.He <970655147@qq.com>
   * @version 1.0
   * @date 2020-02-01 16:33
   */
  private static class InstanceClass 
    private String str;
    public InstanceClass(String str) 
      this.str = str;
    
  


在 foo 方法里面 下图的地方打上一个断点 

基于 HSDB 的可视化调试

jps 查看当前进程 pid 

启动 hsdb, 连接到 当前进程 

Tool >> Object Histogram 查看 Test16HSDBInspectClass$InstanceClass 的信息, 可以发现 三个实例, 我们依次看下 这三个实例 

第一个是 Test16HSDBInspectClass.staticInstance, 被在 Test16HSDBInspectClass.class 对应的 oop 引用

第二个是被一个 Test16HSDBInspectClass 实例引用, 这个 Test16HSDBInspectClass 实例被 main线程 栈上的引用 所引用 

第三个是被 main线程 栈上的引用 所引用 

基于 HSDB 命令行的调试

再来通过 revptrs 来看下 引用这三个 实例的情况呢 

revptrs 0x00000007bf07cba0
null
Oop for java/lang/Class @ 0x00000007bf073b58
hsdb> inspect 0x00000007bf073b58
instance of Oop for java/lang/Class @ 0x00000007bf073b58 @ 0x00000007bf073b58 (size = 112)
<<Reverse pointers>>: 
staticInstance: Oop for com/hx/test03/Test16HSDBInspectClass$InstanceClass @ 0x00000007bf07cba0 Oop for com/hx/test03/Test16HSDBInspectClass$InstanceClass @ 0x00000007bf07cba0

hsdb> revptrs 0x00000007bf07cc18
Oop for com/hx/test03/Test16HSDBInspectClass @ 0x00000007bf07cc08
hsdb> inspect 0x00000007bf07cc08
instance of Oop for com/hx/test03/Test16HSDBInspectClass @ 0x00000007bf07cc08 @ 0x00000007bf07cc08 (size = 16)
<<Reverse pointers>>: 
_mark: 1
_metadata._compressed_klass: InstanceKlass for com/hx/test03/Test16HSDBInspectClass
instance: Oop for com/hx/test03/Test16HSDBInspectClass$InstanceClass @ 0x00000007bf07cc18 Oop for com/hx/test03/Test16HSDBInspectClass$InstanceClass @ 0x00000007bf07cc18

hsdb> revptrs 0x00000007bf07cc60
null
null
hsdb> 

在 main线程 栈中的这个 Test16HSDBInspectClass$InstanceClass 实例, revptrs 扫描不到对应的引用, 呵呵 R大 似乎是说明了一下 原因吧

不过 好在至少我们有一个完善的方法 能够找到 引用这个实例 的引用 

栈帧信息

从 hsdb 上面截取栈帧信息如下图 

我们详细的拆分一下 main, foo 方法的栈帧的相关信息 如下  

0x00007000070d28b8	0x00007000070d28b8 : expression bottom
0x00007000070d28c0	0x0000000119ce507a : byte code pointer
0x00007000070d28c8	0x00007000070d2910 : pointer to locals
0x00007000070d28d0	0x0000000119ce51d0 : constants pool cache
0x00007000070d28d8	0x0000000000000000 : method data oop
0x00007000070d28e0	0x0000000119ce50a8 : method oop
0x00007000070d28e8	0x0000000000000000 : last java stack pointer
0x00007000070d28f0	0x00007000070d2918 : old stack pointer
0x00007000070d28f8	0x00007000070d2958 : old frame pointer
0x00007000070d2900	0x000000010a8dd35d : return address[entry_point's address]
0x00007000070d2908	0x00000007bf07cc60 : localInstance
0x00007000070d2910	0x00000007bf07cc08 : thisInstance
-------------------------------------- foo -------------------------------------------
0x00007000070d2918	0x00007000070d2918 : expression bottom
0x00007000070d2920	0x0000000119ce4fc8 : byte code pointer
0x00007000070d2928	0x00007000070d2968 : pointer to locals
0x00007000070d2930	0x0000000119ce51d0 : constants pool cache
0x00007000070d2938	0x0000000000000000 : method data oop
0x00007000070d2940	0x0000000119ce4fe0 : method oop
0x00007000070d2948	0x00007000070d2918 : last java stack pointer
0x00007000070d2950	0x00007000070d2968 : old stack pointer
0x00007000070d2958	0x00007000070d29d0 : old frame pointer
0x00007000070d2960	0x000000010a8d57a7 : return address[entry_point's address]
0x00007000070d2968	0x00000007bf07cbf8 : args
-------------------------------------- main -------------------------------------------

这里可以 清晰的 看到 第三个 Test16HSDBInspectClass$InstanceClass 的引用 

完 

参考

借HSDB来探索HotSpot VM的运行时数据

以上是关于30 借HSDB来探索HotSpot VM的运行时数据的主要内容,如果未能解决你的问题,请参考以下文章

hsdb

初次尝试java虚拟机调试-启动HSDB

初次尝试java虚拟机调试-启动HSDB

运用HSDB查看jvm运行时数据

HSDB - HotSpot debugger

第一次使用HSDB