【超详细】Java各种类型所占用的内存空间究竟多大?

您所在的位置:网站首页 java下载要多少内存 【超详细】Java各种类型所占用的内存空间究竟多大?

【超详细】Java各种类型所占用的内存空间究竟多大?

2024-07-10 22:41:41| 来源: 网络整理| 查看: 265

文章目录 准备工作对象内存占用情况使用Jprofiler进行验证【关于Retained Size的意思】 基本类型的包装类型内存占用数组占用内存空间String 对象内存占用空间总结

准备工作

不喜欢被蒙在鼓里的感觉,鉴于网上大神们说法不一致,我决定亲自实验,探究究竟Java各个类型占用空间情况。

实验环境为 jdk1.8 hotspot虚拟机+win10系统使用Jprofiler进行探究(IDEA插件直接下载) 在这里插入图片描述另外还需要下载jprofile.exe,下载地址,破解方法百度既能找到!关于jprofiler的具体使用先参考:这篇文章,具体之后再总结。关于对象的内存布局,以及JVM的压缩指针,之前记录过了,具体看【这篇文章】即可! 对象内存占用情况

已知:Java对象的内存布局包括:1.对象头;2.实例数据;3.补充数据;

在jdk6之后的版本中,指针压缩是被默认开启的,开启指针压缩,对象头占用12bytes(其中markword 8字节,Klasspointer 4字节),不开启指针压缩则对象头占用16bytes(其中markword 8字节,Klasspointer 8字节)。【如果为数组还会存储数组长度,上面链接指向的文章中都有记录】

至于实例数据,原生类型(primitive type)的内存占用如下: 下面图片是我在别处截的,这个图存在一些问题。。这也是为什么自己想亲自写博客输出的原因之一,不喜欢被蒙在鼓里不清不楚的感觉。。 boolean在作为数组的时候会被编译器翻译成bytes[ ],所以只占一个字节,但是在单独作为实例变量的时候,boolean会被编译器翻译成int,占4个字节,所以具体多大还得具体分析! 在这里插入图片描述

至于实例数据中的,对象引用:开启指针压缩的内存优化,对象引用占用4字节,不开启的话占用8字节。

补充数据,是将当前的对象大小向上按照8字节的倍数进行补充,其原因上文连接中也介绍了。

使用Jprofiler进行验证

【注意使用Jprofile查看内存,不能让主线程立马结束,不然查看不了内存占用状况,需要写个sleep】

写个例子测试一下,下面是一个Wang的类,其中是一些实例变量 class Wang { private String name; private int age; private int[] arr = {1, 2, 3}; private boolean status; }

我们写个main方法进行测试一下这个对象占用了多少个字节

public static void main(String[] args) throws InterruptedException { Wang wang = new Wang("wangz7",18,true); Thread.sleep(600 * 1000); System.out.println(wang); }

如图:我们发现这个对象占用了32个字节 (推测:对象头12字节 + String4字节 + int4字节 + arr数组引用4字节 + boolean4字节 + 6字节的补充数据) 在这里插入图片描述

【关于Retained Size的意思】

指的是:该对象指向别的对象,导致别的对象称为可达对象,那么Retained大小就包括自身的对象大小 + 指向的对象大小。

在这里wang对象持有了两个引用(String和int[ ]),说明这个String对象加上数组共占用64-32=32字节大小

引用关系如图所示 在这里插入图片描述

基本类型的包装类型内存占用 是否开启指针压缩开启关闭Byte, Boolean16 bytes24 bytesShort, Character16 bytes24 bytesInteger, Float16 bytes24 bytesLong, Double24 bytes24 bytes

可以这么理解。只要是关闭指针压缩,那么一个包装对象在堆中就占用24字节空间 如果开启了指针压缩,那么除了双精度double以及Long这两个基本类型占8字节的包装类型,堆中占用还是24字节,其他的基本类型对应的包装类型均占16字节。

数组占用内存空间

探究这个问题我们可以用到这个工具:openjdk.jol 先添加依赖:

org.openjdk.jol jol-core 0.14

然后可以参考我这个例子【这里写了个对象数组,并打印其对象内存占用情况】

class Wang { private String name; private int age; private int[] arr = {1, 2, 3}; private boolean status; public Wang(String name, int age, boolean status) { this.name = name; this.age = age; this.status = status; } } public class Solution { public static void main(String[] args) throws InterruptedException { System.out.println(VM.current().details()); Wang[] wang = new Wang[10]; System.out.println(ClassLayout.parseInstance(new Wang[10]).toPrintable()); } }

输出: 在这里插入图片描述

在64位机器上,开启压缩指针的情况下,对象头中会使用4个字节来描述数组长度,如上图(如果未开启,那么会通过8个字节进行存储数组长度)因此对象头开启指针压缩占16个字节,不开启指针压缩占16+8=24字节。注意一下,数组占用内存空间就不算对象中的一个个实例对象了,而是只保存引用,所以实例数据部大小 = 数组长度 * 引用4字节从上图倒数第二行可以知道,这个wang数组对象共占用56字节,推导一下(对象头占用16字节 + 数组长度10 * 引用4字节 = 56 字节!)下图为使用Jprofiler查看wang数组的大小,可以看到是56字节 在这里插入图片描述- 为了严谨点实验,我们将数组增大到11的长度再试试其大小是否大了?

在这里插入图片描述- 用jol打印发现确实跟上面描述的一样,刚好64字节

在这里插入图片描述 在这里插入图片描述

Integer[10]数组同样是56字节(对象头16 + 数组长度 * Integer引用类型4字节 = 56字节)

在这里插入图片描述- int[10]同样也是56字节(但是虽然占用内存相等,但是原因不同。这里注意是int类型,是长度 * int4字节,而不是上面的Integer引用类型占4字节)

在这里插入图片描述

String 对象内存占用空间 首先注意!String对象计算内存的时候有一些不同!因为String底层其实是使用数组实现的,但String又不完全由数组构成,还有成员变量hash值…因此计算String对象占用内存的时候需要既考虑到String对象本身,又要考虑到char[ ]的占用大小,并相加!考虑到JDK1.9对String底层数据结构进行了优化(将char[ ]数组优化成了Byte[ ]数组),我们先分析JDK1.7到JDK1.8 String底层是char[ ]数组的情况!补充一个知识点:就是static变量和方法是不与对象进行绑定的,因此使用他们的时候可以不用将对象new出来,直接通过他们的Class模板调用即可,因此他们的引用不是存在对象的实例数据中!而是和类的信息绑定在一起(注意如果是引用对象的话,引用和Class模板绑定,对象依旧在堆中。静态变量在JDK1.7后也均移到了堆中存储,而并非方法区)我们来看看String类的源码: public final class String implements java.io.Serializable, Comparable, CharSequence { private final char value[]; private int hash; private static final long serialVersionUID = -6849794470754667710L; private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; ....省略...

可以看到除了一个char数组和一个int值,其他的是static修饰的不占用对象的内存。

因此一个String对象在开启指针压缩的64位机上,内存大小是(12字节对象头 + char数组引用4字节 + int4字节 + 4字节填充数据 = 24字节) 在这里插入图片描述在这里插入图片描述- 如果关闭了指针压缩的优化方案那么(16字节对象头 + 8字节数组引用 + 4字节int + 4字节补充数据 = 32字节) 在这里插入图片描述

之后再来计算char[ ]数组大小;毕竟String对象有数组的成分,在JDK1.7到JDK1.9之前是char[ ]。因此大小为(16字节对象头 + 字符串长度 * char占用2字节 + 补充数据),因此上面字符串“wang”的char[]数组部分占用16+4*2 = 24字节的大小

因此!在64位机下默认开启指针压缩,String str = new String(“wang”);这个str字符串对象的大小应该是String部分的24字节 + char数组部分的24字节 = 48字节

总结 稍稍了解这里就够了本篇文章主要记录了一下各种类型占用的内存大小,以及使用jol和jprofiler证明对象的大小。关于指针压缩、Retained Size、jprofiler的使用,我会记录下在并把连接放到下面:

————— END —————



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭