2017-06-10 55 views
0

假設我在一臺64位機器上編譯一個帶有gcc的C程序。我假設sizeof(int)是8個字節,而sizeof(char)是1個字節。Java類的內存對齊方式

由於存儲器對準的,下面的結構:

struct example{ 
    int a; 
    char c; 
} 

實際上並不具有的尺寸爲9個字節,但16(兩次sizeof(int)),使得其開始地址和結束地址都可以是的倍數字大小(這裏假定爲8個字節)。

我想知道下面的類將有多大用Java 8:

class Node { 
    int val; 
    Node left, right; 
    boolean flag; 
} 

我基本上不能肯定我們是否會在8首或4個字節的倍數對齊。

回答

2

實際上,JLS或JVMS都沒有指定內存對齊規則。它是平臺特定的。確定字段在內存中如何對齊的唯一方法是:

  • 閱讀JVM源代碼。
  • 檢查由JIT編譯器發出的本地代碼。
  • (可能)使用Unsafe或JNI/JNA代碼來突破抽象層,這些抽象層旨在隔離Java代碼和物理表示的依賴關係。

  • UPDATE:使用「約爾的」工具包 - 見@ ZhekaKozlov的答案

的多少字節用於表示一個對象可以使用Instrumentation.getObjectSize方法來回答的簡單問題:

但是請注意,THI s給出了尺寸的估計值,並且該方法的規範允許許多「實際上意味着什麼」的「擺動空間」。

+0

此外,類型的大小不是類型的真正大小。一個類型的大小不僅僅包含單純的元素。你有方法,構造函數,頭文件,成員類型有自己的開銷,'''''文字,...實例的大小可以變化很大,從零字節到一個寄存器或兩個到幾個字節,包含組合實例的堆上的完整計算大小,具體取決於運行時條件。 –

2

您可以使用jol來了解對象的確切佈局。這是程序的爲你的Node類的輸出(在Oracle JDK 1.8.0_121 64位):

# Running 64-bit HotSpot VM. 
# Using compressed oop with 3-bit shift. 
# Using compressed klass with 3-bit shift. 
# Objects are 8 bytes aligned. 
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] 
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes] 

org.example.Node object internals: 
OFFSET SIZE TYPE DESCRIPTION     VALUE 
    0  4   (object header)    01 00 00 00 (00000001 00000000 00000000 00000000) (1) 
    4  4   (object header)    00 00 00 00 (00000000 00000000 00000000 00000000) (0) 
    8  4   (object header)    70 22 01 f8 (01110000 00100010 00000001 11111000) (-134143376) 
    12  4  int Node.val      0 
    16  1 boolean Node.flag      false 
    17  3   (alignment/padding gap)  N/A 
    20  4 Node Node.left      null 
    24  4 Node Node.right      null 
    28  4   (loss due to the next object alignment) 
Instance size: 32 bytes 
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total 

所以,對準是8個字節。對於32位JVM,它將是4個字節。

請注意,這是平臺特定的。你不應該太依賴這些信息。

+0

啊,對齊信息就在那裏。非常好,謝謝! – Jason