2010-05-07 99 views
11

我剛剛在一本java書中讀到這個聲明,說java中的Objects駐留在堆上。 是否使用了堆,因爲它是快速存儲數據和檢索數據的最佳方式?爲什麼Java使用堆進行內存分配?

我只對數據結構是初學者有一個想法。我的意思是爲什麼不堆疊或其他東西?

+13

如果你正在閱讀一本關於數據結構的書,那麼請注意,在計算機科學中,「heap」有兩個*常見的含義。一個是樹狀數據結構,另一個是內存分配的一般空間。 Java的堆是內存分配的一般空間。 – 2010-05-07 09:56:22

+2

我也一直在想這件事。這很有趣,因爲在我的第一個單身漢中,術語棧堆棧僅用於編程環境。那時我對數據結構一無所知。現在我已經研究了數據結構,我可以理解爲什麼堆棧是堆棧,但不是爲什麼堆是堆。我可以在已經研究過數據結構的人的答案中看到,而誰沒有:)。其實,格雷格上面的評論回答了最好的恕我直言的問題。正如我讀到的:'堆'不一定是'堆'。 http://en.wikipedia.org/wiki/Heap – 2010-09-06 11:46:12

回答

13

堆棧的問題是,您只能刪除最近添加的東西。這適用於局部變量,因爲它們在進入和退出函數時來來去去,但對於生命週期並不遵循單個函數的任意數據而言並不那麼好。內存堆允許您隨意添加和刪除數據。

+0

這個答案在某種程度上非常棒,因爲它解釋了爲什麼堆有時比堆棧更好,使得它聽起來好像堆也需要成爲堆數據結構,從字面上看。這也是非常混亂,以同樣的方式。 – unwind 2010-05-07 09:59:43

+0

@unwind:答案非常簡單,沒有什麼讓人困惑的。你覺得哪些部分令人困惑? – instantsetsuna 2010-08-18 09:03:59

1

由於Java使用垃圾回收器來回收內存,與C和C++不同。在這些語言中,將堆棧用於局部變量*是有意義的。在Java中,沒有一個(局部)變量超出範圍的概念,只有它不再被引用,這使得它有資格進行垃圾回收(在這一點之後,必然會發生)。

*爲清晰起見,並不意味着有在C/C++沒有堆,或者說你不能使用malloc/new家庭分配變量僅局部範圍內使用。

+0

C和C++也使用堆。它通過malloc/free(C和C++)或new/delete(僅限C++)訪問。 OP沒有詢問局部變量,BTW。 – 2010-05-07 09:54:06

+0

@Marcelo坎託斯,當然。我的回答如何表明相反?咄。 – 2010-05-07 09:55:56

+0

我在發表評論後編輯了答案。另外,您修改後的回覆仍然不合格。 OP想知道爲什麼要把對象放在堆上(「爲什麼不是堆棧?」)。你的回答是,「因爲Java使用垃圾收集器......」,這顯然是錯誤的。 – 2010-05-07 10:11:55

1

爲什麼不將對象存儲在堆棧上?那麼,當前正在執行的方法停止執行後,堆棧會發生什麼?

3

堆僅用於vm來分配和釋放內存塊。要訪問對象,可以使用對內存塊的引用(該引用位於堆棧中)。 jvm不允許直接訪問內存(就像在C/C++中一樣)。

1

由於Java中的對象經常超出它們的創建範圍,此時爲該範圍創建的堆棧框架不復存在。

相反的分配的堆空間不會在創建對象的範圍不存在時自動解除分配。

2

這是底層計算模型的工件。內存到操作系統看起來像一個很大的,大多數連續的空間,在這個空間裏數據可以通過地址讀寫。操作系統允許進程通過使用內存地址和讀/寫操作來獲取一塊內存(一個大的連續空間,通常至少有一對K的頁面),並按照他們的喜好進行操作。這個Java堆是建立在它上面的,也就是說對於程序員來說,它看起來像一大堆內存(當然不是,即垃圾回收通常會將東西移動到其他地方)它們實際上不是地址)寫入該內存空間的數據(對象)。這使您可以最大限度地靈活地在其上構建更專用的數據結構。

請記住,它對程序員來說就像一個「堆」,因爲它可以讓你有必要的靈活性,但它不必像這樣實施。它是由垃圾收集器管理的一塊內存,它有一堆數據結構用來完成它的工作,你可以或不可以考慮堆的一部分,也就是說它是由JVM使用和分配的內存,但通常只有程序員可以訪問的內存被認爲是這個上下文中的「堆」。

0

Java可以將對象存儲在堆棧上,如果存在的話轉義分析確定在方法返回時,非本地對象不保留對對象的引用。它不允許你聲明一個對象存儲在堆棧上。

如果Java確實允許對象顯式地位於堆棧上,那麼當方法返回時會發生什麼?由任何非本地對象持有的對本地對象的任何引用會發生什麼?

  • Java的設計者可能決定一些參考可能是無效,導致不確定的行爲,如果取消引用。就像在C/C++中的指針一樣。 Java設計師似乎已經竭盡全力避免未定義的行爲。

  • Java設計者可能已經指定對本地對象的所有引用都變爲null。找到所有這些參考文獻將是困難的。這會導致很難找到由假定不爲null的引用引起的錯誤突然變爲空。包含對象引用的不可變對象是不可能的。並且將引用設置爲null的通知機制必須跨線程工作。所有這些的成本將遠高於本地存儲的優勢。

  • James Gosling是語言設計師之一,擁有Lisp背景,並且這種影響可以通過編譯器或運行時環境優化對象處置(轉義分析) 如果可能的話。