类成员变量在哪里分配
大家都知道,类被加载到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堆里,而不是方法区。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?