Skip to content
zhaopuming edited this page May 16, 2012 · 1 revision

Java内存效率

这篇文章里详细的介绍了JVM中各种数据类型/集合对内存的使用情况。

总的来说:

  1. JVM是非常浪费内存的;

  2. 并且和CPU资源不同,这种浪费,并不能通过JVM自动优化(CPU优化有JIT,内联等技术)

  3. 只能通过小心的使用以及切换到高内存效率的库来实现。

JVM内存浪费在哪里

下图是32位机器中JVM进程的内存地址分布(4G)

JVM内存分布

1. Object

没错,Object是JVM中一切内存浪费的根源

一个Object的内存分配

上图是32位JVM中一个Integer对象的内存占用情况,这个对象共占用128bit内存,其中只有32bit是真正的int数据. 其他的部分:

  1. Class pointer: 指向对象对应的类信息(Class Info)的指针,也就是我们平时用的obj.getClass()
  2. Flags: 各种标志位,包括对象的hashcode,对象是否为数组等信息
  3. Lock: 对象对应的锁,用于synchronized

这三类信息是每一个对象都要存储的,但却不都是真正有用的数据。

结论:Integer对象,内存的使用效率是 1/4

2. 数组

数组比普通的对象多一个size字段,如图:

一个数组对象的内存分配

int[]数组的存储使用率是 1/5,注意这是size==1的情况。如果有更多的数据,int[]数组的内存使用率会提高。

但是Integer[]数组不会

3. String

String的存储大致如下:

class String {
    int count;
    int offset;
    char[] value;
}

内存分布如下图:

一个String对象的内存分配

4. 集合

5. 集合的空余空间

6. 自动可变长

解决方案:

优化小集合

  1. 初始化时指定合理的size
  2. 减少对象的层次

使用高性能的集合/库

1. int[] < Integer[] < ArrayList<Integer> < Set<Integer> < Map<Integer, Integer>
2. Trove

各种原始类型数据的集合:TIntList, TIntIntMap等,接口和java.util里的集合差不多,但是更高效,并且节省大量内存

Javolution real-time goals are simple: To make your application faster and more time predictable!

一个高性能的实时计算库,实时版的 util / lang / text / io / xml

4. Guava

减少抽象的层次

注意不必要的浪费

  1. ConcurrentCollection