類成員變量在哪里分配


大家都知道,類被加載到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堆里,而不是方法區。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM