java各种类型对象占用内存情况分析

 更新时间:2021年04月22日 14:22:10   作者:狮少  
这篇文章主要介绍了java各种类型对象占用内存情况分析,对内存或者性能优化感兴趣的同学,一定要看一下

前言

其实一般的程序猿根本不用了解这么深,只有当你到了一定层次,需要了解jvm内部运行机制,或者高并发多线程下,你写的代码对内存有影响,你想做性能优化。等等等等,一句话,当你想深入了解java对象在内存中,如何存储,或者每个对象占用多大空间时,你会感谢这篇文章

本文主要分析jvm中的情况,实验环境为64位window10系统、JDK1.8,使用JProfiler进行结论验证

很多描述以及 概念是基于你懂基本java知识的,如果你看起来有点吃力,要加油咯

本片更偏重验证,更多理论,请参考:https://segmentfault.com/a/1190000006933272

内存公式:Java对象的内存布 = 对象头(Header) + 实例数据(Instance Data) + 补齐填充(Padding)。

补齐填充:Java对象占用空间是8字节对齐的,即所有Java对象占用bytes数必须是8的倍数

Shallow Size

对象自身占用的内存大小,不包括它引用的对象。
针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。
针对数组类型的对象,它的大小是数组元素对象的大小总和。

Retained Size

Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C, C就是间接引用)
换句话说,Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。
不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。

基本数据类型占用

类型 占用空间
boolean、byte 1byte
short、char 2byte
int、float 4byte
long、double 8byte

接下来用JProfiler验证:

1.新建一个空对象,观察空对象内存占用

public class TestObject {
}

对象占用内存 16b,如图

结论:一般自建空对象占用内存 16b,16 = 12(Header) + 4(Padding)

2.在TestObj中新增一个 int 属性,观察对象内存占用

public class TestObj {
    private int i;

}

对象占用内存 16b,如图

结论:int 占用 4b, 16 = 12(Header) + 4(int)

3.在TestObj中新增一个 long 属性,观察对象内存占用

public class TestObj {
    private long i;

}

对象占用内存 24b,如图

结论:long 占用 8b, 24 = 12(Header) + 8(long) + 4(Padding)

其余基本类型可以参照以上自行验证,原理一样

包装类型占用

包装类(Boolean/Byte/Short/Character/Integer/Long/Double/Float)占用内存的大小 = 对象头大小 + 底层基础数据类型的大小

包装类和其他引用类一样,会产生一个引用(reference)

类型 占用空间
Boolean、Byte 16byte
Short、Char 16byte
Integer、Float 16byte
Long、Double 24byte

1.在TestObj中新增一个 Integer 属性,观察对象内存占用

public class TestObj {
   private Integer  i =128;

}

对象占用内存 32b,如图

结论:Integer 占用 16b, 32 = 12 (Header) + 16(Integer) + 4(reference)

特别的:-128~127 在常量池,只占用 4b,且不产生引用(reference)

2.在TestObj中新增一个 Long 属性,观察对象内存占用

public class TestObj {
   private Long  l = new Long(1);

}

对象占用内存 40b,如图

结论:Long 占用 24b, 40 = 12 (Header) + 24(Long) + 4(reference)

其余包装类型可以参照以上自行验证,原理一样

基本类型数组占用

64位机器上,数组对象的对象头占用24 bytes,启用压缩后占用16字节。比普通对象占用内存多是因为需要额外的空间存储数组的长度(普通16b-12b)。

对象数组本身的大小=数组对象头 + length * 存放单个元素大小

在TestObj中新增一个 char[] 属性,观察对象内存占用

public class TestObj {
   private char[] c = {'a','b','c'};

}

char[] c占用内存 40b,如图

结论:char[3] 占用 24b, 24 = 40 - 16,24 = 16(Header) + 3 * 2(char) + 2(Padding)

封装类型数组占用

封装类型数组比基本类型的数组,需要多管理元素的引用

对象数组本身的大小=数组对象头+length * 引用指针大小 + length * 存放单个元素大小

在TestObj中新增一个 Integer[] 属性,观察对象内存占用

public class TestObj {
    private Integer[] i = {128,129,130};

}

Integer[] i占用内存 80b,如图

结论:Integer[3] 占用 80b, 80 = 96 - 16, 80 = 16(Header) + 3 * 4 (reference)+ 3 * 16(Integer) +4(padding)

String占用内存

在TestObj中新增一个空 String 属性,观察对象内存占用

public class TestObj {
    private String s = new String("");

}

对象占用内存 40b,如图

结论:String 本身占用 24b, 24 = 40 -16也就是说空""也需要16b

注意:这里为什么要写String s = new String("")?请自己思考,不写会怎么样?

答:如果写成String s = “”,是不会再堆中开辟内存的,也就看不到String占用的空间,你看到的将会是下面的,至于为什么,都是因为final

以上就是java各种类型对象占用内存情况分析的详细内容,更多关于java对象占用内存分析的资料请关注脚本之家其它相关文章!

相关文章

  • 详解Java注解实现自己的ORM

    详解Java注解实现自己的ORM

    这篇文章主要介绍了Java注解实现自己的ORM知识,本文通过示例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2022-10-10
  • Java源码解析ArrayList及ConcurrentModificationException

    Java源码解析ArrayList及ConcurrentModificationException

    今天小编就为大家分享一篇关于Java源码解析ArrayList及ConcurrentModificationException,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Spring JdbcTemplate整合使用方法及原理详解

    Spring JdbcTemplate整合使用方法及原理详解

    这篇文章主要介绍了Spring JdbcTemplate整合使用方法及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Java 输入流中的read(byte[] b)方法详解

    Java 输入流中的read(byte[] b)方法详解

    这篇文章主要介绍了Java 输入流中的read(byte[] b)方法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • mybatis Invalid bound statement(not found)排坑记录

    mybatis Invalid bound statement(not foun

    这篇文章主要介绍了mybatis Invalid bound statement(not found)排坑记录,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • springboot layui hutool Excel导入的实现

    springboot layui hutool Excel导入的实现

    本文主要介绍了springboot layui hutool Excel导入的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-03-03
  • Java Servlet请求重定向的方法

    Java Servlet请求重定向的方法

    这篇文章主要介绍了使用Java Servlet请求重定向的方法,帮助大家更好的理解和学习Java Servlet的相关知识,感兴趣的朋友可以了解下
    2020-11-11
  • mapstruct的用法之qualifiedByName示例详解

    mapstruct的用法之qualifiedByName示例详解

    qualifiedByName的意思就是使用这个Mapper接口中的指定的默认方法去处理这个属性的转换,而不是简单的get set,今天通过本文给大家介绍下mapstruct的用法之qualifiedByName示例详解,感兴趣的朋友一起看看吧
    2022-04-04
  • Java内省之Introspector解读

    Java内省之Introspector解读

    这篇文章主要介绍了Java内省之Introspector解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Java三大特性之封装详解

    Java三大特性之封装详解

    面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。 封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。本文将来和大家详细说说Java中的封装,需要的可以了解一下
    2022-10-10

最新评论