博客
关于我
JVM系列之:String,数组和集合类的内存占用大小
阅读量:422 次
发布时间:2019-03-06

本文共 3820 字,大约阅读时间需要 12 分钟。

Java内存分析:String、数组与集合的结构解析

作为一名技术博主,我经常需要深入理解Java对象的内存布局,尤其是面对内存溢出(OOM)问题时,能够通过分析对象结构来找到问题根源。以下将从String、数组以及常见集合的内存布局入手,结合JOL工具的分析结果,带大家一探究竟。

数组的内存布局

首先,让我们从数组的内存布局说起。数组在Java中是非常基础的数据结构,它可以存储多个元素。通过JOL工具,我们可以深入分析一个数组对象的内存布局。

以下是使用JOL工具分析一个数组的输出结果:

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.

可以看到,数组对象的对象头大小为16字节,再加上数组里面的内容长度是15字节,再加上1位补全。最后得到的大小是32字节。这是因为数组的对象头占用了16字节,而数组本身存储的是基础类型的值,这些值在64位JVM中占用了15字节的空间。

需要注意的是,如果数组中存储的是对象类型(如引用),那么每个元素将占用4字节的空间。因此,在实际应用中,选择适当的数据类型对于内存管理至关重要。

String的内存布局

String类在Java中是特殊的,因为它底层是由byte数组实现的。这样看起来似乎有点奇怪,但实际上这是为了提高性能而做出的优化。以下是使用JOL工具分析一个String对象的输出结果:

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字节,接着是一个指向底层byte数组的4字节指针。再加上一些附加字段(如hash、coder和hasIsZero),最终String对象的大小为24字节。需要注意的是,这24字节不包括底层byte数组的大小,实际String的内存占用还包括底层数组的空间。

在JDK9之前,String的底层存储结构是char数组,而在JDK9之后,为了减少内存占用,底层存储结构改为byte数组。这种优化对于存储大量字符数据非常有用。

ArrayList的内存布局

ArrayList是Java中最常用的集合之一,它基于动态数组实现。以下是使用JOL工具分析一个ArrayList对象的输出结果:

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

从输出结果可以看出,ArrayList对象的对象头占用了8字节,接着是modCount和size字段,各占4字节。最后是一个指向底层Object数组的指针,占用4字节。整个ArrayList对象的大小为24字节。需要注意的是,底层数组的大小并不在 ArrayList对象的大小内存中占用,而是单独计算。

其他集合的内存布局

由于篇幅限制,我这里不会详细分析HashMap、HashSet、LinkedList和TreeMap等集合的内存布局。但可以简单提到,这些集合的内存布局通常包括对象头、数据存储区域以及一些管理字段(如计数器)。如果对这些集合的内存布局感兴趣,可以通过JOL工具自行进行分析。

总结

通过对String、数组和ArrayList等Java对象的内存布局分析,我们可以更好地理解它们在内存中的占用情况。选择合适的数据结构和集合类型,对于优化内存使用和解决内存溢出问题具有重要意义。

如果你对集合的内存布局感兴趣,可以继续阅读相关资料,深入探索这些集合在内存中的具体实现细节。希望本文能为你的Java内存分析之旅提供一些帮助!

转载地址:http://oiiuz.baihongyu.com/

你可能感兴趣的文章
opencv5-图像混合
查看>>
opencv6-调整图像亮度和对比度
查看>>
opencv9-膨胀和腐蚀
查看>>
OpenCV_ cv2.imshow()
查看>>
opencv——图像缩放1(resize)
查看>>
Opencv——模块介绍
查看>>
OpenCV与AI深度学习 | 2024年AI初学者需要掌握的热门技能有哪些?
查看>>
OpenCV与AI深度学习 | OpenCV图像拼接--Stitching detailed使用与参数介绍
查看>>
OpenCV与AI深度学习 | OpenCV快速傅里叶变换(FFT)用于图像和视频流的模糊检测(建议收藏!)
查看>>
OpenCV与AI深度学习 | SAM2(Segment Anything Model 2)新一代分割一切大模型介绍与使用(步骤 + 代码)
查看>>
OpenCV与AI深度学习 | YOLO11介绍及五大任务推理演示(目标检测,图像分割,图像分类,姿态检测,带方向目标检测)
查看>>
OpenCV与AI深度学习 | YOLOv11来了:将重新定义AI的可能性
查看>>
OpenCV与AI深度学习 | 使用Python和OpenCV实现火焰检测(附源码)
查看>>
OpenCV与AI深度学习 | 使用PyTorch进行小样本学习的图像分类
查看>>
OpenCV与AI深度学习 | 使用YOLO11实现区域内目标跟踪
查看>>
OpenCV与AI深度学习 | 使用YOLOv8做目标检测、实例分割和图像分类(包含实例操作代码)
查看>>
OpenCV与AI深度学习 | 使用单相机对已知物体进行3D位置估计
查看>>
OpenCV与AI深度学习 | 基于GAN的零缺陷样本产品表面缺陷检测
查看>>
OpenCV与AI深度学习 | 基于OpenCV和深度学习预测年龄和性别
查看>>
OpenCV与AI深度学习 | 基于Python和OpenCV将图像转为ASCII艺术效果
查看>>