歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java中的對象有多大?

習慣了C與語言中精確計算一個結構體,一段數組的所占空間,在使用Java時就有些心裡沒底。雖然知道Integer比int要大,到底大多少?知道String比char[]要大,到底大多少?我甚至一度認為這是與JVM的GC相關的動態數字。 看了幾篇針對性的文章,並做實驗,有了明確的認識。

 

  • 對象內存布局
  • String內存布局
  • 數組內存布局

 

歸納成以下幾個數字化的結論

  • 一個Object需要8字節的housekeeping
  • 一個Object最終占用的字節數要向8字節對齊,即是8的倍數
  • Array一是種特殊的Object,一個Array需要8字節的housekeeping+4字節的length
  • 一個char占用2個字節

關於String,先看一下String的定義

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
{
    /** The value is used for character storage. */
    private final char value[];

    /** The offset is the first index of the storage that is used. */
    private final int offset;

    /** The count is the number of characters in the String. */
    private final int count;

    /** Cache the hash code for the string */
    private int hash; // Default to 0

一個空的String所占用的字節數, 共計40bytes。一個字符都沒寫,40bytes先用去了。 如果寫入10個char,那就是占用40+10*2=60bytes。也由此可見,寫入char的長度多大,越可以攤薄每一個char所占用的空間,畢竟這個40bytes的啟動成本太重了。

  • housekeeping 8bytes
  • char value[] 4+12(reference+itself) = 16bytes
  • offset/count/hash 3*4=12bytes
  • padding 4bytes

 

舉例,在實際工作中,經常遇到一些錯誤的實踐,或者說省事兒的實踐,就是在進行類型定義時,一切皆String。雖然性能優化不是最初該考慮的事情,但有時很快就會遇到不斷調大Xmx,直至崩潰的場景。這裡做一個實驗,並通過JProfile來觀察內存的使用情況。

Java 8簡明教程 http://www.linuxidc.com/Linux/2014-03/98754.htm

Java對象初始化順序的簡單驗證 http://www.linuxidc.com/Linux/2014-02/96220.htm

Java對象值傳遞和對象傳遞的總結 http://www.linuxidc.com/Linux/2012-12/76692.htm

Java對象序列化ObjectOutputStream和ObjectInputStream示例 http://www.linuxidc.com/Linux/2012-08/68360.htm

關於使用Hibernate向數據庫中存取Java對象 http://www.linuxidc.com/Linux/2012-02/53238.htm

JSON轉換為Java對象及日期格式轉換處理 http://www.linuxidc.com/Linux/2012-04/58493.htm

 

String數組

String[] number_array = new String[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE; i++){
 number_array[i] = new String(i+"");   
}

Integer數組

Integer[] number_array = new Integer[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE; i++){
 number_array[i] = new Integer(i);   
}

int數組

int[] number_array = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE; i++){
 number_array[i] = i;   
}

效果
定義ARRAY_SIZE=8M
String數組: 494MB,平均每個String的空間約為66字節,符合預期。
Integer數組: 134MB,平均每個Integer的空間約為17字節,符合預期。
int數組: 40MB,(由於其內部實現為多段不連續的int[],因此加入多個array的空間成本),平均每個int的空間約為5字節,符合預期。
494MB vs 40MB, 12倍左右的差距,非常明顯的改善。雖然我們在定義如同HashMap的類型時,無法直接使用int,退一步講,對於ID類型的Key,使用Integer也要比String有明顯的空間壓縮。記住,一個空的String占40字節!

Copyright © Linux教程網 All Rights Reserved