文章目录

  • 准备工作
  • 对象内存占用情况
    • 使用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, Boolean 16 bytes 24 bytes
Short, Character 16 bytes 24 bytes
Integer, Float 16 bytes 24 bytes
Long, Double 24 bytes 24 bytes

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


数组占用内存空间

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

<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.14</version>
</dependency>

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

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 Stringimplements java.io.Serializable, Comparable<String>, 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 —————

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

  1. 超详细Java安装教程

    超详细Java安装教程 一.Java JDK下载 二.环境变量配置 一.Java JDK下载 下载方式: 官网下载 下载地址: https://www.oracle.com/java/technolo ...

  2. 解析一个Java对象占用多少内存空间

    说明: alignment, 对齐, 比如8字节的数据类型long, 在内存中的起始地址必须是8的整数倍. padding, 补齐; 在对象所占据空间的末尾,如果有空白, 需要使用padding来补齐 ...

  3. 内存对齐 | 原来字段顺序还能影响结构体占用的内存空间

    大家好啊,不知道看了网管在上周的文章Go指针的使用限制和unsafe.Pointer突破之路,你们有没有感觉Golang 比之前想的还好用呢?确实能直接读写内存,很多以前觉得无能为力的事情就不再是问题 ...

  4. PHP数组到底占用多少内存空间

    http://www.ituring.com.cn/article/498349 本文翻译自 nikic 的一篇博文. PHP中的数组到底占用多大的空间? 简要:这篇文章我并不是按照原文逐字逐句的都翻 ...

  5. 有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。 给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转

    有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度. 给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转 ...

  6. 超详细——Java面试高频

    目录 1.基础题 1.1面向对象和面向过程的区别 1.2 Java 语言有哪些特点 1.3 Java 和 C++的区别 1.6 字符型常量和字符串常量的区别 1.7 基本类型 1.8 构造器 Cons ...

  7. 超详细Java学习知识点-不定更新

    练气期 一.了解 jvm就是Java虚拟机 通过这个进行编译 可以实现跨平台 jre包括jvm和运行java的核心库 jdk包含jre和开发工具:javac.exe 和 java.exe 二.开始he ...

  8. 微信支付-超详细java开发-小程序对接

    文章目录 前言 微信支付接入前准备 1.思路介绍 2.如何注册小程序账号? 3.如何接入微信支付,需要准备哪些东西? 4.小程序接入前的准备(APPID及mchid以上两步已拿到,只需配置一下API ...

  9. 一看你就懂,超详细java中的ClassLoader详解

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 ClassLoader翻译过来就是类加载器,普通的java开发者其实用到的不多,但对于某些框架开发者来说却非常常见.理解ClassL ...

最新文章

  1. Java垃圾回收之老年代垃圾收集器
  2. 弹性网络_理论物理所建立解析模型研究凝胶网络弹性介导的液液相分离现象
  3. gevent.hub.LoopExit: ('This operation would block forever'
  4. 阿里巴巴拿下奥运顶级赞助商
  5. ftp服务器网页空白,ftp服务器网页空白
  6. html语言 怎么清除用户名 name= password=,在html页面中填写注册表单后,它会给出这个错误,并使用用户名和密码并将值存储在登录表单中...
  7. c++返回指针时候注意提防_提防Java中的函数式编程!
  8. cs架构用什么语言开发_我为什么建议Python开发者将ES6作为第二语言
  9. 如何使用加密芯片完成SHA1摘要运算
  10. DiskFileItemFactory类的使用
  11. JavaScript Module Pattern
  12. python文件操作:文件指针移动、修改
  13. ivar和property
  14. Oracle分页查询
  15. 二级计算机c语言各题型,计算机二级C语言都有哪些题型?
  16. java毕业设计汽车零件厂绩效管理mybatis+源码+调试部署+系统+数据库+lw
  17. 我的世界java作弊怎么开_我的世界怎么开作弊?如何启用作弊模式?
  18. DirectX11 屏幕截图
  19. 黑马程序员--技术网站网址2
  20. 家具销售管理系统/家具在线商城

热门文章

  1. PC端和移动端唤起QQ聊天
  2. 俄罗斯地名 中文、英文、俄文
  3. 经验分享:win10系统自动关机被阻止的解决方法
  4. 测绘技能大赛-虚拟仿真数字测图(外业部分)
  5. java qq号码生成规则_只需亿小串代码,教你用java仿制qq
  6. JavaScript实现美女时钟
  7. 说说我们项目组的例行会议 (转)
  8. 发泄解压必备神器html5游戏在线玩,解压模拟器压力释放神器
  9. 一款有意思的flash音乐游戏
  10. 阿里资深架构师:初识混沌工程(上)