内存占用估算方法
优质博文:IT-BLOG-CN
通过掌握每种数据类型的大小,就可以更准确地预测对象和数据的内存消耗。
一、基础数据类型
Java
基础数据类型结构,在64
位系统开启指针压缩情况下的内存占用字节数:
boolean | byte | char | short | int | long | float | double | 引用 |
---|---|---|---|---|---|---|---|---|
1 | 1 | 2 | 2 | 4 | 8 | 4 | 8 | 4 |
这些基础数据类型是轻量级的,应尽可能多地使用他们以减少内存消耗。
二、对象内存占用情况
Java
对象的内存占用包括标记字mark word
、类指针klass pointer
、数据字段(实例变量)以及填充padding
markword | klass pointer | data | padding |
---|---|---|---|
8 | 4 | 所有字段占用内存之和 | 将内存占用补齐至8的整数倍 |
由此可见,一个没有任何数据字段的空对象,也会占用16
字节的内存空间
三、数组内存占用
数组在Java
中是一种特殊类型的对象,它还包括一个额外的数组长度字段。数组的内存占用包括标记字、类指针、数组长度字段、数组元素以及填充。与对象类型,数组的占用长度也必须是8
的倍数。需要注意的是,数组元素的大小取决于元素的类型和数量。
markword | klass pointer | 数组长度字段 | 数组元素 | padding |
---|---|---|---|---|
8 | 4 | 4 | 所有字段占用内存之和 | 将内存占用补齐至8的整数倍 |
四、String对象内存占用
这里,我们以Java8
为例说说空String
的内存占用情况,我们来看看String
类中的成员变量。
/** The value is used for character storage. */
private final char value[];/** Cache the hash code for the string */
private int hash; // Default to 0/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
根据上面我们对对象和数组内存的分析以及String
的成员属性可以得出一个空String
对象所占用的内存空间,如下所示。
对象头(8 字节)+ 引用 (4 字节 ) + char 数组(16 字节)+ 1个 int(4字节)+ 1个long(8字节)= 40 字节
如果String
字符串的长度大于0
的话,我们也可以得出String
占用内存的计算公式,如下所示。
40 + 2 * n
五、内存占用分析工具
位了更准确地估计内存占用情况,我们可以借助一些内存分析工具。
jol-core
是一个java
官方推出的jar
包,地址为GitHub-openjdk/jol
pom
依赖:
<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.14</version>
</dependency>
JOL
中常用的几个方法:
ClassLayout.parseInstance(obj).toPrintable():查看对象内部的内存布局;
ClassLayout.parseInstance(obj).instanceSize():计算对象的大小,单位为字节;GraphLayout.parseInstance(obj).toPrintable():查看对象外部信息,包括引用的对象;
GraphLayout.parseInstance(obj).totalSize():查看对象占用空间总大小;
注:除了parseInstance(Object obj)
外,还有parseClass(Class<?> class)
,用法基本相同。
代码使用场景:
public class JolTest {public static void main(String[] args) {Object obj = new Test();// 查看对象内部信息System.out.println(ClassLayout.parseInstance(obj).toPrintable());}
}
class Test{private long p;private byte p1;private short p2;
}
六、防止内存膨胀的策略
【1】使用基础类型代替String
: 在处理业务时,短字符串(如城市三字码)频繁出现。标准String
对象在Java
中占用至少50
字节内存,这对于仅包含2-3
个字符的字符串来说是一种浪费。我们可以使用CodeUtil
工具将这些字符串编码为原生数据类型,从而显著降低内存占用并可能提升性能。
将字符串编码为浮点数和解码为字符串
public class Main {public static void main(String[] args) {String doubleString = "123.45";// 将字符串编码为浮点数double encodedDouble = CodeUtil.encodeToDouble(doubleString);System.out.println("Encoded Double: " + encodedDouble);// 将浮点数解码为字符串String decodedDoubleString = CodeUtil.decodeFromDouble(encodedDouble);System.out.println("Decoded Double String: " + decodedDoubleString);String input = "Hello, World!";// 使用CodeUtil工具将字符串编码为char[]char[] encodedChars = CodeUtil.encodeToCharArray(input);// 打印编码后的char数组System.out.println("Encoded char array:");for (char c : encodedChars) {System.out.print(c + " ");}}
}
输出:
Encoded Double: 123.45
Decoded Double String: 123.45Encoded char array:
H e l l o , W o r l d !
【2】使用对象池: 在某些业务场景中,可能存在大量完全相同或相似的对象。位了减少这些对象的内存占用,可以使用对象池技术来重用这些对象。通过对象池,我们可以确保相同的对象在内存中只有一份拷贝,从而节省大量的内存空间。需要注意的是,在使用对象池技术时,需要确保对象的正确性和线程安全性。
【3】限制容器最大容量: HashMap
等容器类在Java
中广泛使用,但他们没有容量上限。如果不断向容器中添加元素,它们会持续扩容以及容纳更多的元素,从而导致内存占用不断增加。为了避免这种情况的发生,我们使用具有容量限制的容器类(如Guava Cache
)来替代HashMap
等无限制容器。这样可以将内存占用控制在一个合理范围内,防止内存膨胀现象的发生。需要注意的是,在设置容量限制时,需要根据实际业务需求和系统性能进行合理权衡。
相关文章:

内存占用估算方法
优质博文:IT-BLOG-CN 通过掌握每种数据类型的大小,就可以更准确地预测对象和数据的内存消耗。 一、基础数据类型 Java基础数据类型结构,在64位系统开启指针压缩情况下的内存占用字节数: booleanbytecharshortintlongfloatdoub…...

拓扑排序简介
拓扑排序(Topological Sort)是一种重要的图算法,用于对有向无环图(DAG, Directed Acyclic Graph)中的节点进行排序。拓扑排序的结果是一种线性序列,使得对于图中的任意一条有向边(u, v),顶点u都在顶点v之前。这种排序常用于任务调度、编译器依赖关系分析等领域。 拓…...
使用iTextPDF库时,设置文字为中文格式
在使用iTextPDF库时,设置文字为中文格式主要涉及选择合适的中文字体,并确保该字体能够正确渲染中文字符。由于iTextPDF的内置字体通常不支持中文,因此你需要加载一个支持中文的字体文件(如TrueType字体,.ttf文件&#…...

Windows环境下使用Docker配置MySQL数据库
用Docker配置数据库,无论是做开发,还是做生产部署,都非常的方便 它不需要单独安装数据库,也不用担心出现各种环境的配置问题。 本文将分享用Docker配置数据库的步骤,这里用MySQL举例。 其他的数据库如MSSQL…...

快速上手C语言【上】(非常详细!!!)
目录 1. 基本数据类型 2. 变量 2.1 定义格式 和 命名规范 2.2 格式化输入和输出(scanf 和 printf) 编辑 2.3 作用域和生命周期 3. 常量 4. 字符串转义字符注释 5. 操作符 5.1 双目操作符 5.1.1 算数操作符 5.1.2 移位操作符 5.1.3 位操作符…...

[深度学习][python]yolov11+deepsort+pyqt5实现目标追踪
【算法介绍】 YOLOv11、DeepSORT和PyQt5的组合为实现高效目标追踪提供了一个强大的解决方案。 YOLOv11是YOLO系列的最新版本,它在保持高检测速度的同时,通过改进网络结构、优化损失函数等方式,提高了检测精度,能够同时处理多个尺…...
【CSDN入门级教程】
这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...
二叉搜索树 (BST) 节点插入、查找、删除、获取最大值、最小值和中序遍历排序等功能
二叉搜索树 (BST) 实现总结 本程序实现了一个简单的二叉搜索树 (BST),支持节点插入、查找、删除、获取最大值、最小值和中序遍历排序等功能。以下是各部分的详细说明。 数据结构 节点定义 struct BinTreeNode {int data; // 节点存储的数…...

unity ps 2d animation 蛇的制作
一、PS的使用 1.打开PS 利用钢笔工具从下往上勾勒填充 2.复制图层,Ctrl T,w调为-100% 3.对齐图层并继续用钢笔工具进行三角勾勒 3.画眼睛,按U快捷键打开椭圆工具,按住Shift可以画圆,填充并复制图层对称。 4.画笔工具,打开小…...

39 C 语言枚举类型、枚举常量、枚举变量、枚举的遍历、枚举数组、枚举与 switch
目录 1 什么是枚举 2 定义枚举类型 2.1 语法格式 2.2 枚举元素的特点 2.3 案例演示 3 枚举变量 3.1 什么是枚举变量 3.2 定义枚举变量的多种方式 3.3 案例演示 1:标准版枚举类型 3.4 案例演示 2:简化版枚举类型 3.5 案例演示 3:匿…...

LabVIEW程序怎么解决 Bug?
在LabVIEW开发过程中,发现和解决程序中的Bug是确保系统稳定运行的关键环节。由于LabVIEW采用图形化编程方式,Bug的排查和处理与传统编程语言略有不同。以下是解决LabVIEW程序中Bug的常见方法和技巧,涵盖从问题发现到解决的多个步骤和角度&…...
AR智能眼镜之战:Meta vs Snap
随着增强现实(AR)技术的发展,各大科技公司都在争夺下一代计算平台的领先地位。Meta(前身为Facebook)和Snap作为其中的两个重要玩家,正在竞相开发能够提供沉浸式体验的AR智能眼镜。在这篇文章中,我们将深入探讨这两家公司可能采用的显示技术和用户体验,并分析它们各自的…...

Spring Boot 集成 Flowable UI 实现请假流程 Demo
博客主页: 南来_北往 系列专栏:Spring Boot实战 在现代企业应用中,工作流管理是一个至关重要的部分。通过使用Spring Boot和Flowable,可以方便地构建和管理工作流。本文将详细介绍如何在Spring Boot项目中集成Flowable UI,…...

毕业设计选题:基于ssm+vue+uniapp的医院管理系统小程序
开发语言:Java框架:ssmuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:M…...

自动驾驶系列—线控悬架技术:自动驾驶背后的动力学掌控者
🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中…...

CTF刷题buuctf
[WUSTCTF2020]颜值成绩查询 拿到相关题目,其实根据功能和参数分析。需要传入一个学号然后进行针对于对应的学号进行一个查询,很可能就会存在sql注入。 其实这道题最难的点,在于过滤了空格,因此我们使用 /**/来过滤空格的限制。…...

Qt QWidget控件
目录 一、概述 二、Qwidget常用属性及函数介绍 2.1 enable 2.2 geometry 2.3 windowTitle 2.4 windowIcon 2.5 cursor 2.6 font 设置字体样式 2.7 toolTip 2.8 focusPolicy焦点策略 2.9 styleSheet 一、概述 widget翻译而来就是小控件,小部件。…...

如何通过Dockfile更改docker中ubuntu的apt源
首先明确我们有一个宿主机和一个docker环境,接下来的步骤是基于他们两个完成的 1.在宿主机上创建Dockerfile 随便将后面创建的Dockerfile放在一个位置,我这里选择的是 /Desktop 使用vim前默认你已经安装好了vim 2.在输入命令“vim Dockerfile”之后,…...
[C++][第三方库][jsoncpp]详细讲解
目录 1.介绍2.jsoncpp3.使用1.main.cc2.序列化3.反序列化 1.介绍 json是一种数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据json数据类型:对象、数组、字符串、数字 对象:使用{}括起来的表示一个对象数组:使用[…...
JavaScript中decodeURIComponent函数的深入解析与应用指南
在Web开发中,经常需要对URI(统一资源标识符)进行编码和解码,以保证数据传输的准确性和可靠性。decodeURIComponent函数是JavaScript中用于解码由encodeURIComponent函数或其他类似方法编码的部分统一资源标识符(URI&am…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...

华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...

负载均衡器》》LVS、Nginx、HAproxy 区别
虚拟主机 先4,后7...

[拓扑优化] 1.概述
常见的拓扑优化方法有:均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有:有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...

路由基础-路由表
本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中,往往存在多个不同的IP网段,数据在不同的IP网段之间交互是需要借助三层设备的,这些设备具备路由能力,能够实现数据的跨网段转发。 路由是数据通信网络中最基…...