2008-11-14 48 views
14

我真的在研究按值傳遞和Java如何分配對象以及java如何將對象放在堆棧上的差異。一般問題:Java有堆和本地堆棧。你能訪問堆中的任何對象嗎?

有無論如何訪問分配在堆上的對象嗎? java執行什麼機制來保證正確的方法可以從堆中訪問正​​確的數據?

看起來好像如果你很狡猾,甚至可能在運行時操縱java字節碼,那麼當你不應該這樣做時,你可能能夠從堆中操縱數據?

+1

好問題 - 我希望我更瞭解java;一個很好的答案將是我的啓示:) – 2008-11-14 03:33:21

回答

17

JVM指令集中沒有任何指令允許任意訪問堆。因此,字節碼操作在這裏不會幫助你。

JVM還有一個驗證器。它檢查每個方法的代碼(作爲一個類正在被加載),以驗證該方法不會嘗試從執行堆棧中彈出更多的值,而不是將其推送到其上。這確保方法不能「看到」其調用方法所指向的對象。

最後,局部變量存儲在每個方法數組(稱爲「局部變量數組」)中。同樣,驗證器確保來自該數組的每條讀/寫指令都指定一個小於數組大小的索引。請注意,這些JVM指令只能指定一個常量索引。他們無法獲得計算值並將其用作索引。

因此,要回顧一下,答案是

+0

我剛剛回到這個。所以基本上Java的結構和類似的垃圾收集,基於堆棧的語言是這樣的,當你沒有權限的時候,你不能任意訪問堆的一部分。 – 2011-08-16 03:00:58

9

Java中的所有對象都位於堆上。我不太清楚「從堆中訪問對象」的含義。存儲在堆棧中的唯一東西是調用到當前上下文中的函數列表及其局部變量和參數。所有本地變量和參數都是原始類型或引用。

如果您使用new(這是分配非基元類型的唯一方式;這包括數組類型)分配對象,則該對象將分配在堆上,並且該對象的引用將存儲在堆棧或堆,取決於引用存儲在局部變量/參數中還是作爲另一個對象的成員。

當作爲參數傳遞給函數時,所有對象都通過引用傳遞 - 如果函數修改參數,原始對象也會被修改。同樣,也可以說對象引用是按值傳遞的 - 如果你改變一個參數來引用一個新對象,它將繼續在該函數的持續時間內引用該對象,但是傳入的原始對象仍然會參考之前提到的任何內容。原始類型也通過值傳遞。

+0

還有其他的方式來分配新的對象(克隆,Class.newInstance(),反序列化),但他們都是最終堆在堆上。 – 2008-11-14 05:03:49

+4

「人們也可以說對象引用是按值傳遞的」解釋是唯一準確的。說對象通過引用傳遞是不準確的。基本上Java只有傳遞值,就像C. – 2008-11-14 07:11:44

4

關於堆棧上的對象號,它只是從SUN新的Java 6 VM(也許還有一些其他)將嘗試通過將對象優化字節碼堆棧。通常情況下,所有對象都將進入堆中。僅供參考,請查看:http://www.ibm.com/developerworks/java/library/j-jtp09275.html

此外,JVM規格爲http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#6348。 JVM通過簡單地不給你需要的指示來保護它的堆。 JVM實現中的缺陷可能會導致您的里程數發生變化。