查看静态变量对应的对象在是否在堆中

方法区和GC堆是不冲突的两个概念,在JVM规范中,方法区被定义为一种逻辑区域,而方法区具体怎么实现是各JVM的实现细节,所以方法区的内容在堆里也好,不在堆里也好都是符合标准的。

比如曾经HotSpot中,永久代就约等于方法区,而IBM的J9以及在Java7以后的HotSpot中就不是这样设计的;至于本题中的静态实例,目前的HotSpot是在堆中存储的。

另:如果题主有类似的疑问,又是使用的Oracle的JDK的话,可以启动sun.jvm.hotspot.HSDB(在JDK目录/lib/sa-jdi.jar里)来加载一段简单的Java代码,然后获取到你感兴趣的某一个变量oop的内存地址,工具可以查询到这个内存地址在JVM的存储位置。

 

实践一下:

以下操作在Oracle JDK 1.8.0_144下完成。

先编写如下代码:

public class Main {

    private static String a = "test";

    private static Main b = new Main();

    public static void main(String... args) {

    }

}

存在两个静态变量,一个字符串,一个Main,运行时使用HSDB连接这个运行中的虚拟机,得到两个oop的地址:

查看静态变量对应的对象在是否在堆中

查看确实是那个字符串和Main:

查看静态变量对应的对象在是否在堆中

再进一步查看他们的位置:

查看静态变量对应的对象在是否在堆中

可见两个静态变量都在Java堆中。