zoukankan      html  css  js  c++  java
  • 类成员变量在哪里分配

    大家都知道,类被加载到JVM是放在所谓的方法区: JDK7之前是持久代(PermGen),JDK7开始是元空间(metaspace)。所以不免也会简单地认为,类的成员变量(变量本身,而不是变量指向的对象)也是分配在方法区里。

    本篇呢,就通过HSDB这个工具,来分析下类的静态变量到底在哪里分配,同时熟悉下如何使用HSDB这个工具查看Java内存信息。

    一、启动Java进程

    我们通过debug模式运行如下代码,将断点放在打印System.out.println("test")这一行:

    package hsdb
    public class Test {
    
        static Test t1 = new Test();
    
        public static void main(String[] args)throws Exception {
            System.out.println("test");//此行打断点
        }
    }

    二、启动HSDB

    通过如下命令启动HSDB:

    sudo java -cp .:$JAVA_HOME/lib/sa-jdi.jar sun.jvm.hotspot.HSDB

    会弹出如下窗口:

     

    执行jps -ml获取上边我们运行的Test类的pid,然后在HSDB窗口点击File-->Attach to HotSpot process,输入Test的pid,点击ok。

    三、分析

    现在我们的HSDB已经连接上了我们的Test进程。如下图:

     

    选择Tools-->Object Histogram,可以看到Test进程里的所有对象列表,如图:

    输入我们的Test类的类名,找到Test类的实例对象,然后双击。得到对象所在内存的地址,如下图:

     

    有了Test对象所在的内存地址后,我们就可以反向查找:谁拥有指向Test对象的引用。点击Windows-->Console打开控制台,按enter后执行"revptrs Test对象地址" 命令,如下图:

     

    从结果中我们可以看到,是一个Class类型的对象里有一个指向Test对象的引用。这个Class类型的对象地址是0x0000000795786878

    通过Class类型的对象地址,我们查看下Class类型对象的内容。
    点击HSDB窗口Tools-->Inspector,然后输入Class类型对象的地址后敲enter,得到如下图:

    我们可以看到,在Class类型的对象里,确实有一个t1变量指向了Test对象,通过指向的地址,可以判断就是我们之前搜索到的Test类型的对象。

    到这里我们知道了,t1这个类成员变量,被放在了Class类型的对象里,我们只要确定这个Class类型对象所在内存的位置,也就知道了t1变量所在内存的位置。

    点击Tools-->Heap Parameters 显示堆内存的地址范围,如下图:

    通过比较Class类型对象的地址,我们可以看出,Class类型的对象分配在了新生代,即Java堆里,而不是方法区。

  • 相关阅读:
    Java JMX 监管
    Spring Boot REST(一)核心接口
    JSR 规范目录
    【平衡树】宠物收养所 HNOI 2004
    【树型DP】叶子的颜色 OUROJ 1698
    【匈牙利匹配】无题II HDU2236
    【贪心】Communication System POJ 1018
    【贪心】Moving Tables POJ 1083
    Calling Extraterrestrial Intelligence Again POJ 1411
    【贪心】Allowance POJ 3040
  • 原文地址:https://www.cnblogs.com/qingquanzi/p/8945259.html
Copyright © 2011-2022 走看看