博客
关于我
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/

你可能感兴趣的文章
Python Selenium - 获取href值
查看>>
Python Selenium实现自动化测试及Chrome驱动使用!
查看>>
Python Selenium搭建UI自动化测试框架
查看>>
Python Selenium模块详解
查看>>
Python selenium爬取影评生成词云图
查看>>
python selenium自动化测试报告
查看>>
Python selenium自动化测试框架实战 —— 登录测试案例
查看>>
Python Selenium设计模式 —— POM
查看>>
Python Serial:如何使用 read 或 readline 函数一次读取多个字符
查看>>
Python set([]) 如何检查两个对象是否相等?一个对象需要定义哪些方法来自定义它?
查看>>
Python setup.py:数据文件无法复制目录:不存在或不是常规文件
查看>>
Python setuptools sdist:仅安装版本化文件
查看>>
Python Shell下使用matplotlib
查看>>
Python Slice How-to,我知道Python Slice,但我怎么才能使用内置的Slice对象呢?
查看>>
python socket分包发送数据
查看>>
python socket模块_Python socket模块实现TCP服务端客户端
查看>>
Python SOCKS5代理客户端HTTPS
查看>>
Python Soc网络分析:通过使用函数迭代列表来计算机会网络
查看>>
Python SQL和NoSQL数据库操作实战
查看>>
python stdout flush_sys.stdout.flush()方法的用法
查看>>