2012-08-12 1452 views
14

我知道Java使用填充;對象必須是8個字節的倍數。但是,我沒有看到它的目的。它是幹什麼用的?它的主要目的究竟是什麼?爲什麼Java對象必須是8的倍數?

+6

這與JVM相關。 – 2012-08-12 22:45:08

+0

我很抱歉沒有注意到,但我正在談論Hotspot JVM。 – Nando 2012-08-12 23:01:24

+3

然後你不知道 - 你只是在某處讀它。 – 2012-08-12 23:02:59

回答

16

其目的是alignment,它允許以一些空間爲代價加快內存訪問。如果數據未對齊,則處理器需要在加載內存後進行一些轉換才能訪問它。

此外,垃圾回收簡化(並加快)最小分配單元的大小。

Java不需要8字節(64位系統除外),但由於32位體系結構是創建Java時的常態,因此Java標準中可能需要4字節對齊。

+0

我發現話說[百科](http://en.wikipedia.org/wiki/Java_performance#Memory_usage)和[Javamex(http://www.javamex.com/tutorials/memory/object_memory_usage.shtml)此信息它是8個字節。但唯一的目的是垃圾收集? – Nando 2012-08-12 23:00:15

+1

@ user1110725,請仔細閱讀。對齊不僅適用於垃圾收集,還適用於內存訪問。應遵循 – cyroxx 2012-08-12 23:15:54

+0

+1 – 2013-10-08 09:10:11

-1

Java中的數據類型大小是8的位數(非字節)的倍數,因爲大多數現代處理器中的字長是8位的倍數:16位,32位,64位。以這種方式,可以使對象中的字段適合(「對齊」)一個或多個詞並儘可能地浪費空間,利用底層處理器的指令操作字大小的數據。

+5

不是,字節。除了數組中的小原語外,大多數(所有?)JVM都將其數據對齊至少4個字節的邊界。 – U2EF1 2012-08-12 22:49:37

+0

我不是在談論數據類型,而是對象。我的意思是,我自己的對象。它們總是8個字節的倍數。至少,這是我讀的。我發現[Javamex(http://www.javamex.com/tutorials/memory/object_memory_usage.shtml)這個信息[百科](http://en.wikipedia.org/wiki/Java_performance#Memory_usage)和。 – Nando 2012-08-12 22:58:17

4

接受的答案是推測(但部分正確)。這是真正的答案。

首先,對於@ U2EF1的榮譽,8字節邊界的好處之一是8字節是大多數處理器的最佳訪問。但是,這個決定還有更多。

如果您有32位引用,則可以尋址最多2^32或4 GB的內存(實際上,儘管您獲得的更少,但更像3.5 GB)。如果您有64位引用,則可以尋址2^64,即內存爲terrabytes。但是,對於64位引用,一切都趨於放緩並佔用更多空間。這是由於處理64位的32位處理器的開銷,以及由於更少的空間和更多垃圾收集而導致所有處理器上的GC循環更多。

因此,創作者採取了一箇中間立場,並決定使用35位參考,這樣可以達到2^35或32 GB的內存,佔用更少的空間,從而獲得與32位參考相同的性能優勢。這是通過讀取一個32位參考並在讀取時將其左移3位來完成的,並且在存儲參考時將其右移3位。這意味着所有對象必須在2^3邊界(8字節)上對齊。這些被稱爲壓縮的普通對象指針或壓縮的oops。

爲什麼不用36位引用來訪問64 GB內存?那麼,這是一個折衷。您需要大量浪費空間來處理16字節的對齊,並且據我所知,絕大多數處理器不會從16字節對齊中獲得速度優勢,而不是8字節對齊。

請注意,JVM不會打擾使用壓縮的oops,除非最大內存設置爲4 GB以上,而默認情況下它不是。實際上,您可以使用-XX:+UsedCompressedOops標誌啓用它們。

這是在32位虛擬機當天重新提供64位系統上的額外可用內存。據我所知,64位虛擬機沒有限制。 Java性能:權威指南,第8章

來源:Java性能:權威指南,第8章

+1

8字節對齊的決定比壓縮的oops特性要早,也適用於32位JVM,它們不支持超過2GB。你推測「未來的JVM將支持64位引用*」是沒有意義的,因爲所有的64位JVM都支持64位引用。當堆大於32GB或者指定'-XX:-UsedCompressedOops'時,或者使用不具備壓縮的oops功能的較舊的JVM時,會使用它們。 – Holger 2016-06-07 18:19:44

+0

也許措辭不佳,但我的意思是使用_all_ 64位的引用,而不是沒有「存儲在64位值中的引用」。上一次檢查(這是前一段時間),你不能在JVM中使用2^64內存堆。 – 2016-06-08 19:12:39

+0

如果你找到一個支持分配2×4字節的真實系統(硬件+操作系統),我會感到非常驚訝。我想知道,你是否明白,那是多大。但是,您可以使用與底層系統支持的堆一樣大的堆。如果您認爲,您遇到了支持少於操作系統的64位JVM,您必須更具體。 – Holger 2016-06-08 20:04:32

相關問題