我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java中new Object()占用多少个字节

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java中new Object()占用多少个字节

Java中new Object()占用多少个字节?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

对象的指向

先来看一段代码:

package com.zwx.jvm;public class HeapMemory {  private Object obj1 = new Object();  public static void main(String[] args) {    Object obj2 = new Object();  }}

上面的代码中,obj1 和obj2在内存中有什么区别?

我们先来回忆一下JVM系列1的文章中有提到,方法区存储每个类的结构,比如:运行时常量池、属性和方法数据,以及方法和构造函数等数据。所以我们这个obj1是存在方法区的,而new会创建一个对象实例,对象实例是存储在内的,于是就有了下面这幅图(方法区指向堆):

Java中new Object()占用多少个字节

而obj2 是属于方法内的局部变量,存储在Java虚拟机栈内的栈帧中的局部变量表内,这就是经典的栈指向堆:

Java中new Object()占用多少个字节

这里我们再来思考一下,我们一个变量指向了堆,而堆内只是存储了一个实例对象,那么堆内的示例对象是如何知道自己属于哪个Class,也就是说这个实例是如何知道自己所对应的类元信息的呢?这就涉及到了一个Java对象在内存中是如何布局的。

Java内存模型

对象内存中可以分为三块区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding),以64位操作系统为例(未开启指针压缩的情况)Java对象布局如下图所示:

Java中new Object()占用多少个字节

其中对象头中的Mark Word中的详细信息在文章synchronized锁升级原理中有详细介绍。上图中的对齐填充不是一定有的,如果对象头和实例数据加起来刚好是8字节的倍数,那么就不需要对齐填充。

知道了Java内存布局,那么我们来看一个面试问题

Object obj=new Object()占用字节

这是网上很多人都会提到的一个问题,那么结合上面的Java内存布局,我们来分析下,以64位操作系统为例,new Object()占用大小分为两种情况:

  • 未开启指针压缩        占用大小为:8(Mark Word)+8(Class Pointer)=16字节

  • 开启了指针压缩(默认是开启的)        开启指针压缩后,Class Pointer会被压缩为4字节,最终大小为:8(Mark Word)+4(Class Pointer)+4(对齐填充)=16字节

结果到底是不是这个呢?我们来验证一下。首先引入一个pom依赖:

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

然后新建一个简单的demo:

package com.zwx.jvm;import org.openjdk.jol.info.ClassLayout;public class HeapMemory {  public static void main(String[] args) {    Object obj = new Object();    System.out.println(ClassLayout.parseInstance(obj).toPrintable());  }}

输出结果如下:

Java中new Object()占用多少个字节

最后的结果是16字节,没有问题,这是因为默认开启了指针压缩,那我们现在把指针压缩关闭之后再去试试。

-XX:+UseCompressedOops 开启指针压缩-XX:-UseCompressedOops 关闭指针压缩

Java中new Object()占用多少个字节

再次运行,得到如下结果:

Java中new Object()占用多少个字节

可以看到,这时候已经没有了对齐填充部分了,但是占用大小还是16位。

下面我们再来演示一下如果一个对象中带有属性之后的大小。

新建一个类,内部只有一个byte属性:

package com.zwx.jvm;public class MyItem {  byte i = 0;}

然后分别在开启指针压缩和关闭指针压缩的场景下分别输出这个类的大小。

package com.zwx.jvm;import org.openjdk.jol.info.ClassLayout;public class HeapMemory {  public static void main(String[] args) {    MyItem myItem = new MyItem();    System.out.println(ClassLayout.parseInstance(myItem).toPrintable());  }}

开启指针压缩,占用16字节:

Java中new Object()占用多少个字节

关闭指针压缩,占用24字节:

Java中new Object()占用多少个字节

这个时候就能看出来开启了指针压缩的优势了,如果不断创建大量对象,指针压缩对性能还是有一定优化的。

对象的访问

创建好一个对象之后,当然需要去访问它,那么当我们需要访问一个对象的时候,是如何定位到对象的呢?目前最主流的访问对象方式有两种:句柄访问和直接指针访问。

句柄访问        使用句柄访问的话,Java虚拟机会在堆内划分出一块内存来存储句柄池,那么对象当中存储的就是句柄地址,然后句柄池中才会存储对象实例数据和对象类型数据地址。

Java中new Object()占用多少个字节

直接指针访问(Hot Spot虚拟机采用的方式)        直接指针访问的话对象中就会直接存储对象类型数据。

Java中new Object()占用多少个字节

句柄访问和直接指针访问对比

上面图形中我们很容易对比,就是如果使用句柄访问的时候,会多了一次指针定位,但是他也有一个好处就是,假如一个对象被移动(地址改变了),那么只需要改变句柄池的指向就可以了,不需要修改reference对象内的指向,而如果使用直接指针访问,就还需要到局部变量表内修改reference指向。

堆内存

上面我们提到,在Java对象头当中的Mark Word存储了对象的分代年龄,那么什么是分代年龄呢?

一个对象的分代年龄可以理解为垃圾回收次数,当一个对象经过一次垃圾回收之后还存在,那么分代年龄就会加1,在64位的虚拟机中,分代年龄占了4位,最大值为15。分代年龄默认为0000,随着垃圾回收次数,会逐渐递增。

Java堆内存中按照分代年龄来划分,分为Young区和Old区,对象分配首先会到Young区,达到一定分代年龄(-XX:MaxTenuringThreshold可以设置大小,默认为15)就会进入Old区(注意:如果一个对象太大,那么就会直接进入Old区)。

之所以会这么划分是因为如果整个堆只有一个区的话,那么垃圾回收的时候每次都需要把堆内所有对象都扫描一遍,浪费性能。而其实大部分Java对象的生命周期都是很短的,一旦一个对象回收很多次都回收不掉,可以认为下一次垃圾回收的时候可能也回收不掉,所以Young区和Old区的垃圾回收可以分开进行,只有当Young区在进行垃圾回收之后还是没有腾出空间,那么再去触发Old区的垃圾回收。

Java中new Object()占用多少个字节

Young区

现在拆分成了Young区,那我们看下面一个场景,下面的Young是经过垃圾回收之后的一个概图:

Java中new Object()占用多少个字节

假如说现在来了一个对象,要占用2个对象的大小,会发现放不下去了,这时候就会触发GC(垃圾回收),但是一旦触发了GC(垃圾回收),对用户线程是有影响的,因为GC过程中为了确保对象引用不会不断变化,需要停止所有用户线程,Sun把这个事件称之为:Stop the World(STW)。这些在下一篇讲解垃圾回收的时候会详细介绍,这里先不深入。

所以说一般是越少GC越好,而实际上上图中可以看到至少还可以放入3个对象,只要按照对象都按照顺序放好,那么是可以放得下的,所以这就产生了问题了,明明有空间,但是因为空间不连续,导致对象申请内存失败,导致触发GC了,那么如何解决这种问题呢?

解决的思路就是把Young区的对象按顺序放好,所以就产生了一个方法,把Young区再次划分一下,分为2个区:Eden区和Survivor区。

Java中new Object()占用多少个字节

具体操作是:一个对象来了之后,先分配到Eden区,Eden区满了之后,触发GC,经过GC之后,为了防止空间不连续,把幸存下来的对象复制到Survivor区,然后Eden区就可以完整清理掉了,当然这么做是有一个前提的,就是大部分对象都是生命周期极短的,基本一次垃圾回收就可以把Eden区大部分对象回收掉(这个前提是经过测试总结得到的)。

触发GC的时候Survivor区也会一起回收,并不是说单独只触发Eden区,但是这样问题又来了,Eden区是保证空间基本连续了,但是Survivor区又可能产生空间碎片,导致不连续了,所以就又把Survivor区给一分为二了:

Java中new Object()占用多少个字节

这个时候工作流程又变成这样了:首先还是在Eden区分配空间,Eden区满了之后触发GC,GC之后把幸存对象 复制到S0区(S1区是空的),然后继续在Eden区分配对象,再次触发GC之后如果发现S0区放不下了(产生空间碎片,实际还有空间),那么就把S0区对象复制到S1区,并把幸存对象也复制到S1区,这时候S0区是空的了,并依次反复操作,假如说S0区或者S1区空间对象复制移动了之后还是放不下,那就说明这时候是真的满了,那就去老年区借点空间过来(这就是担保机制,老年代需要提供这种空间分配担保),假如说老年区空间也不够了,那就会触发Full GC,如果还是不够,那就会抛出OutOfMemeoyError异常了。

注意:为了确保S0和S1两个区域之间每次复制都能顺利进行,S0和S1两个区的大小必须要保持一致,而且同一时间有一个区域一定是空的。虽然说这种做法是会导致了一小部分空间的浪费,但是综合其他性能的提升来说,是值得的。

Old区

当Young区的对象达到设置的分代年龄之后,对象会进入Old区,Old区满了之后会触发Full GC,如果还是清理不掉空间,那么就抛出OutOfMemeoyError异常。

名词扫盲

上面提到了很多新的名词,而实际上很多这种名词还有其他叫法,这个还是觉得有必要了解一下。

垃圾回收:简称GC。

Minor GC:针对新生代的GC

Major GC:针对老年代的GC,一般老年代触发GC的同时也会触发Minor GC,也就等于触发了Full GC。

Full GC:新生代+老年代同时发生GC。

Young区:新生代

Old区:老年代

Eden区:暂时没发现有什么中文翻译(伊甸园?)

Surcivor区:幸存区

S0和S1:也称之为from区和to区,注意from和to两个区是不断互换身份的,且S0和S1一定要相等,并且保证一块区域是空的

一个对象的人生轨迹图

从上面的介绍大家应该有一个大致的印象,一个对象会在Eden区,S0区,S1区,Old区不断流转(当然,一开始就会被回收的短命对象除外),我们可以得到下面的一个流程图:

Java中new Object()占用多少个字节

看完上述内容,你们掌握Java中new Object()占用多少个字节的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网行业资讯频道,感谢各位的阅读!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java中new Object()占用多少个字节

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java中new Object()占用多少个字节

Java中new Object()占用多少个字节?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。对象的指向先来看一段代码:package com.zwx.jvm;public c
2023-06-06

java中long类型占多少字节

所谓的占用字节数 就是申请内存的时候所占的空间大小。long 8字节 最小值是 -9,223,372,036,854,775,808(-2^63);最大值是 9,223,372,036,854,775,807(2^63 -1);java中其他类型所
java中long类型占多少字节
2019-09-27

c++中int占多少字节

c++ 中 int 类型占用的字节数取决于系统的体系结构:32 位体系结构:4 个字节64 位体系结构:8 个字节C++ 中 int 占多少字节?int 是 C++ 中的基本整数类型,它占用的字节数取决于系统的体系结构。在大多数现代系统中
c++中int占多少字节
2024-05-12

c语言中int占用多少字节

在c语言中,int型变量所占字节数由编译器的实现决定:32位编译器中通常占用4个字节(32位);64位编译器中通常占用8个字节(64位)。C语言中int占用多少字节在C语言中,int型变量所占的字节数取决于编译器的实现。对于32位编译器,
c语言中int占用多少字节
2024-05-12

ascii中一个字符占多个个字节

这篇文章给大家分享的是有关ascii中一个字符占多个个字节的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。ascii一个字符占一个字节,ASCII码使用指定的7位或8位二进制数组合来表示128或256种可能的字符;
2023-06-14

python中浮点数占多少字节

今天就跟大家聊聊有关python中浮点数占多少字节,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。python有哪些常用库python常用的库:1.requesuts;2.scrapy
2023-06-14

java中的数据类型各占多少字节(位)

java中有8种基本数据类型:byte、int、short、long、boolean、char、float、double对应的类为:Byte、Int、Short、Long、Boolean、Charecter、Float、Double其中:boolean是逻辑型
java中的数据类型各占多少字节(位)
2019-01-10

java中字符串占几个字节

首先,char为Java的基本类型,基本类型所占的字节数是固定的,如int占4字节,double占8字节,这可以使得Java在不同的平台上所占类型固定,很好地保证了Java的可移植性。因此,Java中char类型固定占2个字节。(注:char类型也可以存储一个
java中字符串占几个字节
2020-07-12

c语言中char类型数据占多少个字节

本篇内容介绍了“c语言中char类型数据占多少个字节”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!c语言中char类型数据占1个字节,因为c
2023-06-21

java中int类型占几个字节

java中几种数据类型所占的字节数如下:由上图可以看到java中的int占4个字节。字节(Byte )是计算机信息技术用于计量存储容量的一种计量单位,作为一个单位来处理的一个二进制数字串,是构成信息的一个小单位。最常用的字节是八位的字节,即它包含八位的二进制数
java中int类型占几个字节
2018-05-09

php中一个汉字是多少个字节

小编给大家分享一下php中一个汉字是多少个字节,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!在php中对于中文字符,若使用GBK、Big-5版本,每个中文字符相当于2个字节;若使用UTF-8版本,每个中文字符相当于3个字节
2023-06-25

计算机网络中在ascii码文件中一个英文字母占多少个字节

这篇文章主要介绍了计算机网络中在ascii码文件中一个英文字母占多少个字节,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在ascii码文件中一个英文字母占一个字节,一个中文汉
2023-06-25

C语言中字符串abc在内存占用多少字节数

本篇内容介绍了“C语言中字符串abc在内存占用多少字节数”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!字符串abc在内存占用的字节数是4,因
2023-06-26

java中的char占几个字节实例分析

java中的char占几个字节实例分析 1:“字节”是byte,“位”是bit ;  2: 1 byte = 8 bit ;  char 在Java中是2个字节。java采用unicode,2个字节(16位)来表示一个字符。  
2023-05-31

一个Java字符串中有多少个字符

本篇内容主要讲解“一个Java字符串中有多少个字符”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“一个Java字符串中有多少个字符”吧!依照Java的文档, Java中的字符内部是以UTF-16编
2023-06-16

Java中char字节占用的示例分析

这篇文章给大家分享的是有关Java中char字节占用的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Java有哪些集合类Java中的集合主要分为四类:1、List列表:有序的,可重复的;2、Queue队列
2023-06-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录