前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >JVM系列之:String,数组和集合类的内存占用大小

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

作者头像
程序那些事
发布于 2020-07-23 11:42:58
发布于 2020-07-23 11:42:58
66300
代码可运行
举报
文章被收录于专栏:程序那些事程序那些事
运行总次数:0
代码可运行

程序那些事

简介

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

数组

先看下JOL的代码和输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//byte arraylog.info("{}",ClassLayout.parseInstance("www.flydean.com".getBytes()).toPrintable());

输出结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 bytesSpace 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来分析:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Stringlog.info("{}",ClassLayout.parseInstance("www.flydean.com").toPrintable());

输出结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 bytesSpace 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:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Array Listlog.info("{}",ClassLayout.parseInstance(new ArrayList()).toPrintable());

输出结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 bytesSpace losses: 0 bytes internal + 0 bytes external = 0 bytes total

画个图来直观的表示:

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

HashMap

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

HashSet

LinkedList

treeMap

来个比较复杂的TreeMap:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序那些事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
皕杰报表(yum的安装)
当在linux上使用yum时,提示错误,This system is not registered to Red Hat Subscription Management,这是因为如果使用redhat的yum源是需要注册付费的。因此咱们就要更改yum源来使它免费,咱们来使用163的源。
用户10133222
2022/11/07
3380
centos7下卸载python后yum不能使用的恢复方法
手贱!本来是想把python2.7重新安装一下,结果直接remove了。然后使用yum install python的时候发现已经command not found了。无奈,百度谷歌一起上,找到了恢复方法。 按照你的系统版本下载对应的rpm包(rpm包下载地址:http://mirrors.ustc.edu.cn) 安装python ├── python-2.7.5-48.el7.x86_64.rpm ├── python-devel-2.7.5-48.el7.x86_64.rpm ├── python
行 者
2018/03/26
1.6K0
centos7下卸载python后yum不能使用的恢复方法
Centos下安装yum(完整教程)
如果找不到以上版本,可以到http://tel.mirrors.163.com/centos/7/os/x86_64/Packages/下载最新版本
全栈程序员站长
2022/09/05
11.2K0
centos7安装yum[通俗易懂]
yum卸载后软件安装很麻烦,所以重新安装yum,先找到rpm包下载地址。 下载地址:http://mirrors.163.com/centos/7/os/x86_64/Packages/ (我的是centos7 64位,所以是这个路径,看网址就可以知道每个路径是干嘛的,下载自己版本所需的即可, 各个包小版本有变化,注意进行选择)
全栈程序员站长
2022/09/05
8.8K1
CentOS7修复python拯救yum
   本人正在吹着空调,喝着茶水,然后qq头像抖了两下,业务开发同学给我打了个招呼,“忙么?帮个忙可以不?” 这很明显了,要忙了呀!来活了。本着爱岗敬业的精神回复“您说”。 然后很含蓄的告诉我yum不好用了。得嘞,这活可能很简单,就是自己编译了高版本替换了系统python,然后yum使用python,由于版本高,库没有,导致没法使用。  或者特别麻烦,直接把系统的python卸了!!!!!! 这个有可能没救,这要看业务同学是否手下留情了。闲话到此!
py3study
2020/01/08
2.8K2
centos7.6安装yum模块
# cat /etc/redhat-release 版本号为:CentOS Linux release 7.6.1810 (Core)
全栈程序员站长
2022/08/23
1.1K0
CentOS下yum的安装及配置
一般公司都用Linux来搭建服务器,Linux安装软件时能够用yum安装依赖包是一件非常简单而幸福的事情,因为你只需一个简单的安装命令yum install []即可安装相应的软件,yum工具会自动的从网上yum源中下载相应的依赖包,并以正确的依赖关系一个个安装依赖包。下面简单介绍一下CentOS下安装yum源的流程和操作。
全栈程序员站长
2022/09/06
6K0
CentOS下yum的安装及配置
Centos7.4下重新安装yum和python
一次意外的python升级导致了yum不能使用,这就导致通过yum安装行不通了。主要报错信息如下:
joshua317
2022/03/25
2.1K0
修复我服务器上那被我折腾的乱七八糟的centos
事情还得从之前我的一次手欠说起,这一次手欠,给我后续带来了不少的麻烦事,昨天我跟腾讯云的客服一起折腾了一天都没解决,但我今天搞了一个Redhat订阅之后很快就找到了解决方法,由于事情较为漫长且命令输出较多,所以可能没多少可以用来说明具体情况的图片
冰漪叶
2022/10/24
1.2K0
修复我服务器上那被我折腾的乱七八糟的centos
Centos7 安装yum源
https://www.cnblogs.com/guanbin-529/p/11980400.html
全栈程序员站长
2022/09/05
2.6K0
Centos7下误删python2和yum的解决办法
因为云服务器系统被挖矿程序占领之后,开始想尝试将其删除,但是技术不过关,删除之后又重新运行了,没办法只有把重要的代码和数据备份之后,将服务器重置了系统。然后在重新配置安装nginx的时候,误删除了yum。尝试解决办法的时候,又把python2删除了。T.T。只有重新安装python2和yum。找了一圈安装方法,他们的一些源的位置,都已经移除了。发现一个博主写的,还可以。我在这里在总结一下。博主地址: https://www.cnblogs.com/wangjunjiehome/p/9239005.html
Mokwing
2020/09/08
1.9K0
Linux:CentOS 7 安装yum
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/139925.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/03
10.2K0
centos7 重装python和yum
卸载现有的Python和Yum 1、删除现有Python ##强制删除已安装程序及其关联 rpm -qa|grep python|xargs rpm -ev --allmatches --nodeps ##删除所有残余文件 ##xargs,允许你对输出执行其他某些命令 whereis python |xargs rm -frv ##验证删除,返回无结果 whereis python 2、删除现有的yum、强制删除已安装程序及其关联 ##强制删除已安装程序及其关联 rpm -qa|grep yum|xargs rpm -ev --allmatches --nodeps ##强制删除所有残余文件 whereis yum |xargs rm -frv 下载所需的rpm包 ##查看自己系统版本的命令 cat /etc/redhat-release #CentOS Linux release 7.8.2003 (Core) ##下载相应的包地址: http://mirrors.ustc.edu.cn/centos/7.8.2003(自己系统版本号)/os/x86_64/Packages/ ##所需要的包 ##python python-2.7.5-88.el7.x86_64.rpm python-iniparse-0.4-9.el7.noarch.rpm python-pycurl-7.19.0-19.el7.x86_64.rpm python-devel-2.7.5-88.el7.x86_64.rpm python-libs-2.7.5-88.el7.x86_64.rpm python-urlgrabber-3.10-10.el7.noarch.rpm rpm-python-4.11.3-43.el7.x86_64.rpm ##yum yum-3.4.3-167.el7.centos.noarch.rpm yum-metadata-parser-1.1.4-10.el7.x86_64.rpm yum-plugin-fastestmirror-1.1.31-53.el7.noarch.rpm ##创建目录python和yum用以存放rpm包 mkdir /usr/local/rpm ##使用wget分别下载python以及yum的rpm包(注意:一定要和系统的版本号对应) 地址如下 python wget http://mirrors.ustc.edu.cn/centos/7.8.2003/os/x86_64/Packages/python-2.7.5-88.el7.x86_64.rpm wget http://mirrors.ustc.edu.cn/centos/7.8.2003/os/x86_64/Packages/python-iniparse-0.4-9.el7.noarch.rpm wget http://mirrors.ustc.edu.cn/centos/7.8.2003/os/x86_64/Packages/python-pycurl-7.19.0-19.el7.x86_64.rpm wget http://mirrors.ustc.edu.cn/centos/7.8.2003/os/x86_64/Packages/python-devel-2.7.5-88.el7.x86_64.rpm wget http://mirrors.ustc.edu.cn/centos/7.8.2003/os/x86_64/Packages/python-libs-2.7.5-88.el7.x86_64.rpm wget http://mirrors.ustc.edu.cn/centos/7.8.2003/os/x86_64/Packages/python-urlgrabber-3.10-10.el7.noarch.rpm wget http://mirrors.ustc.edu.cn/centos/7.8.2003/os/x86_64/Packages/rpm-python-4.11.3-43.el7.x86_64.rpm
用户8483969
2021/04/09
1.5K0
Linux系统自带Python2&yum的卸载及重装
事情的起因是我昨天在测试Linux安装Python3的shell脚本时,需要卸载Python3重新安装一遍。但是通过如下命令卸载python3时,少写了个3,不小心将系统自带的python2也给删除了。
大刚测试开发实战
2022/11/14
3.1K0
Linux系统自带Python2&yum的卸载及重装
在Centos7的环境下下载安装yum完整过程。
7、点击[yum-metadata-parser-1.1.4-10.el7.x86_64.rpm]
裴来凡
2022/05/28
3.1K0
在Centos7的环境下下载安装yum完整过程。
Linux 系统 Centos 7.7 下重装yum
我的是centos7 ,那么在这个网站页面下寻找,按上面的关键字 http://mirrors.163.com/centos/7.7.1908/os/x86_64/Packages/
张云飞Vir
2020/04/09
2.4K0
Redhad 7改用CentOS7 yum源【亲测】
redhat 默认自带的 yum 源需要注册,才能更新。我们想不花钱,需要替换掉redhat的yum源,最好是国内的源。
程裕强
2022/05/06
1.6K0
Redhad 7改用CentOS7 yum源【亲测】
记一次误删yum源的解决方法
版权声明:本文为木偶人shaon原创文章,转载请注明原文地址,非常感谢。 https://blog.csdn.net/wh211212/article/details/52936492
shaonbean
2019/05/26
2.1K0
python升级或者卸载导致No module named yum
环境cenos7.6 原理:yum命令其实是用python编写,而在https://www.python.org/ftp/python/下载的python编译后是没有yum模块。 解决:要不就指向原有系统默认的python,如果默认的被删除,则需要找到对应系统版本的rpm安装包重新下载。
lovelife110
2021/01/14
3.1K0
手抖把Python2.7卸载了,导致了自己的yum不可用
②Python3系列和Python2系列版本不向下兼容,所以我就卸载了机器自带的Python2.7,删的干干净净.
Lansonli
2021/10/09
1.3K1
相关推荐
皕杰报表(yum的安装)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文