内存占用估算方法

news/2024/10/4 16:17:53/

优质博文:IT-BLOG-CN

通过掌握每种数据类型的大小,就可以更准确地预测对象和数据的内存消耗。

一、基础数据类型

Java基础数据类型结构,在64位系统开启指针压缩情况下的内存占用字节数:

booleanbytecharshortintlongfloatdouble引用
112248484

这些基础数据类型是轻量级的,应尽可能多地使用他们以减少内存消耗。

二、对象内存占用情况

Java对象的内存占用包括标记字mark word、类指针klass pointer、数据字段(实例变量)以及填充padding

markwordklass pointerdatapadding
84所有字段占用内存之和将内存占用补齐至8的整数倍

由此可见,一个没有任何数据字段的空对象,也会占用16字节的内存空间

三、数组内存占用

数组在Java中是一种特殊类型的对象,它还包括一个额外的数组长度字段。数组的内存占用包括标记字、类指针、数组长度字段、数组元素以及填充。与对象类型,数组的占用长度也必须是8的倍数。需要注意的是,数组元素的大小取决于元素的类型和数量。

markwordklass pointer数组长度字段数组元素padding
844所有字段占用内存之和将内存占用补齐至8的整数倍

四、String对象内存占用

这里,我们以Java8为例说说空String的内存占用情况,我们来看看String类中的成员变量。

java">/** 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对象所占用的内存空间,如下所示。

java">对象头(8 字节)+ 引用 (4 字节 )  + char 数组(16 字节)+ 1int4字节)+ 1long8字节)= 40 字节

如果String字符串的长度大于0的话,我们也可以得出String占用内存的计算公式,如下所示。

java">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中常用的几个方法:

java">ClassLayout.parseInstance(obj).toPrintable():查看对象内部的内存布局;
ClassLayout.parseInstance(obj).instanceSize():计算对象的大小,单位为字节;GraphLayout.parseInstance(obj).toPrintable():查看对象外部信息,包括引用的对象;
GraphLayout.parseInstance(obj).totalSize():查看对象占用空间总大小;

注:除了parseInstance(Object obj)外,还有parseClass(Class<?> class),用法基本相同。

代码使用场景:

java">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工具将这些字符串编码为原生数据类型,从而显著降低内存占用并可能提升性能。

将字符串编码为浮点数和解码为字符串

java">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等无限制容器。这样可以将内存占用控制在一个合理范围内,防止内存膨胀现象的发生。需要注意的是,在设置容量限制时,需要根据实际业务需求和系统性能进行合理权衡。


http://www.ppmy.cn/news/1534500.html

相关文章

Stable Diffusion绘画 | 插件-Deforum:动态视频生成(上篇)

Deforum 与 AnimateDiff 不太一样&#xff0c; AnimateDiff 是生成丝滑变化视频的&#xff0c;而 Deforum 的丝滑程度远远没有 AnimateDiff 好。 它是根据对比前面一帧的画面&#xff0c;然后不断生成新的相似图片&#xff0c;来组合成一个完整的视频。 Deforum 的优点在于可…

github/git密钥配置与使用

零、前言 因为要在ubuntu上做点东西&#xff0c;发现git clone 的时候必须输账户密码&#xff0c;后来发现密码是token&#xff0c;但是token一大串太烦了&#xff0c;忙了一天发现可以通过配置 公钥 来 替代 http 的 部署方式。 一、生成 ssh 密钥对 我们先测试下能不能 连接…

ETLCloud携手ClickHouse:高效的数据查询效率

自从大数据处理技术走进大众视野、开源项目Hadoop的出现&#xff0c;以前受制于数据库处理能力的大数据技术蓬勃发展&#xff0c;传统关系型数据库所构建的数据仓库&#xff0c;被以Hive为代表的大数据技术所取代&#xff0c;随着技术不断发展&#xff0c;Hadoop虽然带来了诸多…

Object.values() 、 Object.keys()

拿到当前对象里面的value值 // 假设你有一个对象 const myObject {name: Kimi,age: 30,country: Moon };// 获取对象的所有值 const values Object.values(myObject);// 输出值数组 console.log(values); // ["Kimi", 30, "Moon"] 如果你需要在 Vue 组…

使用 Vue3 和 Axios 实现 CRUD 操作

文章目录 1、准备工作2、创建 Vue 3 项目3、项目结构4、实现 CRUD 操作5、运行项目6、小结在当今的前端开发中,Vue.js 作为一款流行的 JavaScript 框架,正在被越来越多的开发者所青睐。尤其是 Vue 3 引入了 Composition API 和更优雅的响应式处理,使得模板编写和状态管理变得…

Build a Large Language Model (From Scratch)学习汇总

目录 中文理解代码电子书全文中文翻译第1章&#xff1a;理解大型语言模型第2章&#xff1a;处理文本数据第3章&#xff1a;编码Attention机制第4章&#xff1a;从零实现GPT模型第5章&#xff1a;在未标记数据上进行预训练第6章&#xff1a;用于文本分类的微调第7章&#xff1a;…

行为设计模式 -策略设计模式- JAVA

策略设计模式 一 .简介二. 案例2.1 抽象策略&#xff08;Strategy&#xff09;类2.2 具体策略&#xff08;Concrete Strategy&#xff09;类2.3 环境&#xff08;Context&#xff09;类2.4 测试 三. 结论3.1 优缺点3.2 使用场景 前言 这是我在这个网站整理的笔记,有错误的地方请…

Docekrfile和docker compose编写指南及注意事项

Dockerfile 基础语法 我们通过编写dockerfile,将每一层要做的事情使用语法固定下来&#xff0c;之后运行指令就可以通过docker来制作自己的镜像了。 构建镜像的指令&#xff1a;docker build /path -t imageName:tag 注意&#xff0c;docker build后的path必须是dockerfile…