简介

之前的文章中,我们使用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. 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程序那些事

本文来源:flydean的博客

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

java string 内存占用_JVM系列之:String,数组和集合类的内存占用大小相关推荐

  1. js byte数组转string_JVM系列之:String,数组和集合类的内存占用大小

    简介 之前的文章中,我们使用JOL工具简单的分析过String,数组和集合类的内存占用情况,这里再做一次更详细的分析和介绍,希望大家后面再遇到OOM问题的时候不再抱头痛哭,而是可以有章可循,开始吧. ...

  2. java jvm内存分配_JVM系列一:JVM内存组成及分配

    java内存组成介绍:堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚 ...

  3. java内存可视化_JVM系列(六)、可视化工具介绍

    1. Jconsole 1.1 Jconsole 介绍 Jconsole(Java Monitoring and Management Console)是从java5开始,是一种基于JMX(java ...

  4. jvm内存结构_JVM系列之内存结构

    JVM的内存结构大概分为: 堆(Heap):线程共享.所有的对象实例以及数组都要在堆上分配.回收器主要管理的对象. 堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分成三部分,Eden ...

  5. java 查看垃圾收集器_JVM系列:查看JVM使用的什么垃圾收集器

    一.方法一 打印虚拟机所有参数 [root@localhost ~]# java -XX:+PrintFlagsFinal -version | grep : uintx InitialHeapSiz ...

  6. JAVA学习3-抽象类、内部类、数组、Object、System、String、基本包装类型

    21.类之间的关系 is a:继承关系 has a : 关联关系,通常以属性的形式存在 like a:实现关系,通常是类与接口的关系; 22.抽象类与接口的区别 抽象类是半抽象的,接口是完全抽象的: ...

  7. Java 7 源码学习系列(一)——String

    String表示字符串,Java中所有字符串的字面值都是String类的实例,例如"ABC".字符串是常量,在定义之后不能被改变,字符串缓冲区支持可变的字符串.因为 String ...

  8. Redis从入门到放弃系列(一) String

    Redis从入门到放弃系列(一) String 本文例子基于:5.0.4 字符串是Redis中最常见的数据结构,底层是采用SDS,是可以修改的字符串,类似ArrayList,采用预分配冗余空间的方式来 ...

  9. java内存区域_JVM学习之—Java内存区域

    为了加深对Java语言的理解,加深对Java虚拟机工作机制.底层特性的了解和掌握,准备在闲暇时间,抽空对<深入理解Java虚拟机 JVM高级特性与最佳实践>一书进行学习.本文是学习此书第2 ...

最新文章

  1. css表示第一个元素和最后一个元素,CSS第一个和最后一个子元素
  2. 全球及中国太阳能硅片产业供需走势及投资建设前景分析报告2021-2027年
  3. yunyang tensorfow-yolo3 训练时权重文件消失的原因和解决办法(max_to_keep)
  4. 2021第一季度云智能生态技术服务能力盘点
  5. 数据库水平切分的实现原理解析——分库,分表,主从,集群,负载均衡器(转)...
  6. python 最简单的实现适配器设计模式
  7. 操作系统上机作业--实现mysys(多进程)
  8. Redux初学者指南
  9. java运行命令解释
  10. pagex,screenx,clientx的差别
  11. 单片机c语言程序编写歌谱,51单片机播放音乐简谱的函数库
  12. sql server2000的1433端口不通怎么办
  13. 基于涂鸦智能开发板的墨水屏座位管理器——1.电路设计篇
  14. 华硕主板装系统蓝屏_装xp系统蓝屏,电脑安装xp系统蓝屏怎么办
  15. 针孔相机模型成像原理与图像变形矫正教程
  16. AUTOSAR I-PDU的理解以及I-PDU的Callout
  17. 保卫萝卜迅玩版53关php,2018微信保卫萝卜迅玩版第50关攻略
  18. 目标检测算法横向比较,包括backbone、特征融合、loss、proposal/anchor/heatmap、NMS、正负样本设置等
  19. Lua Busted 单元测试简介(Windows 环境)
  20. 计算机窗口键,电脑上win是哪个键_电脑windows键是哪个-win7之家

热门文章

  1. Latex设置字体大小
  2. android远程命令行工具,Android 使用 adb命令 远程安装apk
  3. php redis 队列抢红包_php+redis实现消息队列
  4. hybbs接口php,HYBBS
  5. 仪征市第二中学计算机老师,静心倾听花自开 ——仪征市第二中学徐丞老师
  6. DS树+图综合练习--构建邻接表
  7. eclipse和jdk的版本问题,比如printf()出错
  8. windows,python3.x下安装pyspider
  9. [转]hadoop新手错误解决方法
  10. HashMap两种遍历数据的方式