关于java:JVM系列之String数组和集合类的内存占用大小

11次阅读

共计 2737 个字符,预计需要花费 7 分钟才能阅读完成。

简介

之前的文章中,咱们应用 JOL 工具简略的剖析过 String, 数组和汇合类的内存占用状况,这里再做一次更具体的剖析和介绍,心愿大家前面再遇到 OOM 问题的时候不再抱头痛哭,而是能够有章可循,开始吧。

数组

先看下 JOL 的代码和输入:

//byte array
log.info("{}",ClassLayout.parseInstance("www.flydean.com".getBytes()).toPrintable());

输入后果:

INFO com.flydean.CollectionSize - [B 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)                           22 13 07 00 (00100010 00010011 00000111 00000000) (463650)
     12     4        (object header)                           0f 00 00 00 (00001111 00000000 00000000 00000000) (15)
     16    15   byte [B.<elements>                             N/A
     31     1        (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 0 bytes internal + 1 bytes external = 1 bytes total

留神,本文的论断都在 64 位的 JVM 中运行得出了,并且开启了 COOPs 压缩对象指针技术。

能够看到数组对象的对象头大小是 16 字节,再加上数组外面的内容长度是 15 字节,再加上 1 位补全。最初失去的大小是 32 字节。

同样的,咱们计算存有 100 个对象的数组,能够失去上面的论断:

留神最初面的 Object 数组,如果数组中存储的不是根底类型,那么实际上存储的是执行该对象的指针,该指针大小是 4 个字节。

String

String 是一个十分非凡的对象,它的底层是以 byte 数组存储的。

留神,在 JDK9 之前,String 的底层存储构造是 char[], 一个 char 须要占用两个字节的存储单位。

因为大部分的 String 都是以 Latin- 1 字符编码来示意的,只须要一个字节存储就够了,两个字节齐全是节约。

于是在 JDK9 之后,字符串的底层存储变成了 byte[]。

同样的咱们还是用 JOL 来剖析:

//String
log.info("{}",ClassLayout.parseInstance("www.flydean.com").toPrintable());

输入后果:

INFO com.flydean.CollectionSize - java.lang.String object internals:
 OFFSET  SIZE      TYPE DESCRIPTION                               VALUE
      0     4           (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4           (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4           (object header)                           77 1a 06 00 (01110111 00011010 00000110 00000000) (399991)
     12     4    byte[] String.value                              [119, 119, 119, 46, 102, 108, 121, 100, 101, 97, 110, 46, 99, 111, 109]
     16     4       int String.hash                               0
     20     1      byte String.coder                              0
     21     1   boolean String.hashIsZero                         false
     22     2           (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 2 bytes external = 2 bytes total

能够看到 String 中的对象头是 12 字节,而后加上 4 字节的指针指向一个 byte 数组。再加上 hash,coder,和 hasIsZero 属性,最初的大小是 24 字节。

我这里应用的是 JDK14 的 String 版本,不同的版本可能有所不同。

当然这只是这个 String 对象的大小,不蕴含底层数组的大小。

咱们来计算一下 String 对象的实在大小:

String 对象的大小 +byte 数组的大小 =24+32=56 字节。

ArrayList

咱们构建一个非常简单的 ArrayList:

//Array List
log.info("{}",ClassLayout.parseInstance(new ArrayList()).toPrintable());

输入后果:

INFO com.flydean.CollectionSize - java.util.ArrayList object internals:
 OFFSET  SIZE                 TYPE DESCRIPTION                               VALUE
      0     4                      (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4                      (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                      (object header)                           87 81 05 00 (10000111 10000001 00000101 00000000) (360839)
     12     4                  int AbstractList.modCount                     0
     16     4                  int ArrayList.size                            0
     20     4   java.lang.Object[] ArrayList.elementData                     []
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

画个图来直观的示意:

这里 modCount 和 size 的初始值都是 0。

HashMap

因为文章篇幅的限度,这里就不把代码列出来了,我只贴个图上来:

HashSet

LinkedList

treeMap

来个比较复杂的 TreeMap:

总结

本文用图形的模式形象的展现了汇合对象,数组和 String 在内存中的应用状况。

前面的几个汇合我就没有一一计算,有趣味的敌人能够在下方回复你计算的后果哟。

本文作者:flydean 程序那些事

本文链接:http://www.flydean.com/jvm-collections-size/

本文起源:flydean 的博客

欢送关注我的公众号: 程序那些事,更多精彩等着您!

正文完
 0