2015-04-21 369 views
1

如何自引用是否存儲在堆棧內存中。例如,假設,在堆棧內存中存儲引用

A a = new A(); 

a也應存放在內存,並應該有一個內存地址嗎?

如果我解釋更多,如果我們打印System.out.println(a)它將打印「對象A」的內存地址。但是,我怎樣才能打印參考a的內存地址?

更正:如果我們打印System.out.println(a)將打印的「物體A」對象的不是內存地址A

回答

1

但是我怎樣才能打印參考a的內存地址?

你不能,很簡單。 JVM規範沒有以任何方式定義堆棧的基本屬性,嚴格按照規範進行定義,但不保證它甚至有內存地址。實際上,在當前的實現中,當然是這樣,但規範保留了未定義的規則,因此Java沒有用於檢查堆棧內存佈局的接口。

此外,應該注意的是,實際上,堆棧變量根本不能保證有內存地址。它們完全駐留在寄存器中並且不會被刷新到內存中並不罕見。

但是,也應該提到的是,不像你說的話,System.out.println(a)打印對象的地址通過a簡稱。它所打印的內容也沒有被規範定義,但是Oracle的實現打印了a的身份哈希碼,而不是它的地址。地址a甚至不能保證在其整個生命週期內保持不變,因爲GC可能會移動它。

+0

糾正其「a」的哈希碼 – Harshana

0

你的假設是錯誤的哈希碼; System.out.println(a);將打印句柄的地址的對象,而不是objcet本身:

在某些Java虛擬機的Oracle的實現,一個 引用一個類的實例是一個指向一個句柄,其本身 一對指針:一個表包含對象的方法和一個指向Class對象的指針,該對象表示對象的類型爲 ,另一個是從堆中爲 分配的內存對象數據。

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.7

作爲JVM「有權」到存儲器中執行期間移動的事情,給JVM對象本身不會被保證是對任何可用的參考。實際上,當Java執行垃圾收集時,它不保證將轉發指針放置到活動對象的新地址,這使得垃圾收集可能會呈現JVM地址(即使您可以獲得它)也沒有用處。

請參閱http://www.cs.cornell.edu/courses/cs312/2003fa/lectures/sec24.htm瞭解垃圾收集如何工作的簡單說明。

+0

我不明白「對象的句柄的地址」的含義。正如你所提到的「a」cosider作爲指針,它自己應該存儲在內存中的指針知道。我所理解的是指針「a」具有作爲對象A的哈希碼的值。 – Harshana

+0

已更新的答案。 – EvenLisle

0

System.out.println(a)打印a.hashCode()(除非a.toString()被重寫),它不一定是a的地址。