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简明教程

Java对象初始化顺序的简单验证

Java对象值传递和对象传递的总结

Java对象序列化ObjectOutputStream和ObjectInputStream示例

关于使用Hibernate向数据库中存取Java对象

JSON转换为Java对象及日期格式转换处理

 

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字节!

本文永久更新链接地址:

相关内容

    暂无相关文章