内存占用估算方法

优质博文: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类中的成员变量。

/** 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 字节)+ 1int4字节)+ 1long8字节)= 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.45

Encoded char array:
H e l l o ,   W o r l d !

【2】使用对象池: 在某些业务场景中,可能存在大量完全相同或相似的对象。位了减少这些对象的内存占用,可以使用对象池技术来重用这些对象。通过对象池,我们可以确保相同的对象在内存中只有一份拷贝,从而节省大量的内存空间。需要注意的是,在使用对象池技术时,需要确保对象的正确性和线程安全性。

【3】限制容器最大容量: HashMap等容器类在Java中广泛使用,但他们没有容量上限。如果不断向容器中添加元素,它们会持续扩容以及容纳更多的元素,从而导致内存占用不断增加。为了避免这种情况的发生,我们使用具有容量限制的容器类(如Guava Cache)来替代HashMap等无限制容器。这样可以将内存占用控制在一个合理范围内,防止内存膨胀现象的发生。需要注意的是,在设置容量限制时,需要根据实际业务需求和系统性能进行合理权衡。

MySQL的内存占用分为两部分:系统内存占用和MySQL进程内存占用。下面分别介绍如何分析这两部分内存占用。 1. 系统内存占用 系统内存占用主要是指MySQL进程使用的操作系统内存,包括缓存、堆栈、共享内存、代码段等。可以使用操作系统工具来分析系统内存占用情况。 Linux系统可以使用top、ps和free等命令来查看系统内存占用情况。例如,使用top命令可以查看系统中各个进程的内存占用情况,包括进程的占用内存、虚拟内存、共享内存等。使用free命令可以查看系统的内存使用情况,包括已用内存、可用内存、缓存等。 Windows系统可以使用任务管理器来查看系统内存占用情况。在任务管理器的“进程”选项卡中,可以查看各个进程的内存占用情况。在“性能”选项卡中,可以查看系统的内存使用情况。 2. MySQL进程内存占用 MySQL进程内存占用主要是指MySQL服务器进程使用的内存,包括缓存、临时表、连接池、查询缓存等。可以使用MySQL内置工具来分析MySQL进程内存占用情况。 可以使用SHOW PROCESSLIST命令来查看MySQL服务器当前的连接情况,包括连接数、连接状态、连接使用的内存等。可以使用SHOW VARIABLES LIKE 'key_buffer_size'、SHOW VARIABLES LIKE 'query_cache_size'等命令来查看MySQL服务器配置的缓存大小,从而估算内存占用情况。 可以使用MySQL自带的性能监控工具Performance Schema来分析MySQL进程内存占用情况。Performance Schema可以监视MySQL服务器的内部活动和性能指标,包括内存占用、CPU占用、I/O等。可以使用Performance Schema相关的视图和表来查询MySQL服务器的内存占用情况,例如: ``` SELECT * FROM performance_schema.memory_summary_global_by_event_name; ``` 以上是一些常用的方法,可以帮助分析MySQL的内存占用情况。需要根据具体情况选择合适的方法进行分析。
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿进阶

千言万语都不及一句“谢谢”

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值