集册 Android&Java 技术笔记 Java对象内存使用

Java对象内存使用

—— Java对象内存的使用情况

欢马劈雪     最近更新时间:2020-08-04 05:37:59

87

一般情况

  • primitive types
  • Object overhead for "housekeeping" information
    recording an object's class, ID and status flags such as whether the object is currently reachable, currently synchronization-locked etc.
    Hotspot JVM:
    • Object类实例:8字节;
    • Object类实例数组:12字节,比Object类实例多了个length域;
  • Object size granularity
    为了便于寻址,对象内存会8字节对齐;
    例子:
    • Object类实例8字节;
    • 只有一个boolean成员的类对象,16字节,有8个boolean成员的类对象,16字节;
    • 有两个long成员、三个int成员、一个boolean成员的类对象,40字节;

数组

  • object header:12个字节,多了一个length域
  • 一维数组,数据区域,length * sizeof(element),此外,对于object是保存的引用,为4字节
  • 二维数组,每一行都是一个数组,故每一行都有object的开销
  • 例子:10*10 int二维数组:
    • 外层header:12字节
    • 外层数据(10个引用):10*4=40字节,加上padding,共56字节
    • 内层每一行,header12字节
    • 内层每一行,数据10*4=40字节,加上padding,每一行共56字节
    • 总共56*11=616字节
  • 更多维的数组逻辑一致

String

  • 一个String对象实际上包含了不止一个对象
  • java的char占两个字节
  • Minimum String memory usage (bytes) = 8 (int) ((((num chars) 2) + 45) / 8)
  • String对象包含:char数组,offset,length,hashcode这四部分内容
  • 空String对象占用内存:8(header) + 3*4(上述三个int域) + 4(char数组引用) + 12(空char数组header) + 4(char数组padding) = 40字节
  • 包含17个字符的String:24 + (12 + 17*2 + 2) = 72字节
  • substring使用时的trick
    • 如果原string和substring都会被使用,则节省了内存
    • 如果原string不再被使用,有可能就会浪费内存
    • 例如:
      原有的char数组并不会被回收,但是只使用了其中的一部分:
      String str = "Some longish string...";
      str = str.substring(5, 4);

      原有的char数据将来会被gc,避免了内存浪费:

      String str = "Some longish string...";
      str = new String(str.substring(5, 4));

string buffers

StringBuffer、StringBuilder等
header: 8字节;length,char数组引用;底层char数组所占内存;
假设初始容量为16的string buffer:16 + 12 + 16*2 + 4 = 64字节
扩容策略是每次倍增容量

减少String占用的内存

展开阅读全文