面试官问我:Object o = new Object() 占用了多少个字节?

小小面试一下

前言蜜语

   最近马师傅火的不要不要的,虽然没有抢到耗子尾汁的商标注册权,可是必须得蹭一波马师傅的热度,下面就是闪电五连鞭的教学环节,你准备好了吗!java

   在正式内容开始前先甩两篇关于类加载机制和内存布局的文章,由于今天的内容多少与这两篇文章有直接的联系,对这方面还比较薄弱的朋友能够先看看,地址我放在下面。面试

jvm┃java内存区域,跳槽大厂必会知识点!算法

moon不讲武德!!!一个类加载机制给面试官说蒙了!!数组

   今天本文的内容就针对刚刚模拟面试两个问题jvm

   1.对象的建立过程布局

   2.对象的内存布局学习

对象的建立过程

如下内容基于HotSpot VM 分代模型线程

这张图其实就能完整的说明一个对象的建立过程到底发生了什么,不少朋友可能一下看不懂,那么咱们就跟着左上角的一步一步来:指针

  1. 一个对象new出来先判断线程栈是否能分配下对象

    • 若是能分配下,直接分配在栈中。
    • 若是分配不下则进行第二步。
  2. 判断该对象是否足够大

    • 若是足够大,则直接进入老年代。
    • 若是不够大,则进行第三步。
  3. 判断建立对象的线程的TLAB(本地线程缓冲区)空间是否足够

    • 若是足够,直接分配在TLAB中。
    • 若是不够,则进入Eden区中其余空间。而后进行第四步。
  4. GC清除

    • 若是清除掉了该对象,则直接结束。
    • 若是没有清除掉对象,进行第5步。
  5. 此刻对象进入Survivor 1 区,判断年龄是否足够大

    • 若是年龄足够大,则直接进入old区域。
    • 若是年龄不够大,则进入Survivor 2 区,而后进入第4步,循环往复。

   经过这张流程图和步骤解析你们应该对一个对象的建立过程有一个很清晰的概念了,可是其中仍是有不少小细节会被忽略,为何jvm会在对象的建立过程当中大做文章,会分这么多种状况?为了让你们更深刻的可以理解它,咱们就再来看看下面这几个问题:

  1. 为何对象会选择先分配在栈中?

   首先栈是线程私有的,将对象优先分配在栈中,能够经过pop直接将对象的全部信息,空间直接清除,当线程消亡的时候也能够直接清理这一起TLAB区域。

  1. 为何jvm会让大对象会直接进入老年代?

   大对象须要连续的空间来存储,若是不存入老年代对jvm说就多是一个负担,若是没有足够的空间就有可能致使提早触发gc来清理空间来安置大对象

  1. 为何会选择先进入TLAB?

   TLAB是线程本地缓冲区,TLAB的好处就是防止不一样线程建立对象选择同一起内存区域而产生竞争,会使其几率大大减小。

  1. 为何会有两个Survivor区?而且存活且年龄不够大的对象会从一个Survivor区转到另外一个Survivor区?

   根据根可达算法,jvm会从开始寻找到全部正在使用的对象,没有使用的就是垃圾,一般状况下,不少对象都是用完就抛弃的,因此真正在Survivor区长时间存活的对象很是少,将这部分对象从一个Survivor区转到另外一个Survivor区后,就能够直接对这个Survivor区进行全量的空间回收了,效率会很高。

对象的内存布局

   做者可不是标题党,哈哈,因此咱们回到文章的标题,Object o = new Object();到底占用多少个字节?这道题的目的其实就是考验看你对对象的内存布局了解的是否清晰,先上图:

   在java中对象的内存布局分为两种状况,非数组对象和数组对象,数组对象和非数组对象的区别就是须要额外的空间存储数组的长度length

对象头

   对象头又分为MarkWord和Class Pointer两部分。

  • MarkWord:包含一系列的标记位,好比轻量级锁的标记位,偏向锁标记位,gc记录信息等等,在32位系统占4字节,在64位系统中占8字节

  • ClassPointer:用来指向对象对应的Class对象(其对应的元数据对象)的内存地址。在32位系统占4字节,在64位系统中占8字节

  • Length:只在数组对象中存在,用来记录数组的长度,占用4字节

Interface data
  • Interface data:对象实际数据,对象实际数据包括了对象的全部成员变量,其大小由各个成员变量的大小决定。(这里不包括静态成员变量,由于其是在方法区维护的)
Padding
  • Padding:Java对象占用空间是8字节对齐的,即全部Java对象占用bytes数必须是8的倍数,是由于当咱们从磁盘中取一个数据时,不会说我想取一个字节就是一个字节,都是按照一起一起来取的,这一块大小是8个字节,因此为了完整,padding的做用就是补充字节,保证对象是8字节的整数倍

   moon在上文特地标注了32位系统和64位系统不一样区域占用空间大小的区别,这是由于对象指针在64位JVM下的寻址更长,因此想比32位会多出来更多占用空间。

   可是如今假设一个场景,公司如今项目部署的机器是32位的,大家老板要让你将项目迁移到64位的系统上,可是又由于64位系统比32位系统要多出更多占用空间,怎么办,由于正常来讲咱们是不须要这一部分多余空间的,因此jvm已经帮你考虑好了,那就是指针压缩

指针压缩

   -XX:+UseCompressedOops 这个参数就是JVM提供给你的解决方案,能够压缩指针,将占用的空间压缩为原来的一半,起到节约空间的做用,classpointer参数大小就受到其影响。

Object o = new Object()到底占用多少个字节?

   经过刚才内存布局的学习后,这个问题就很好回答了,面试官其实就是想问你对象的内存布局是怎样的,咱们这里就针对这个问题的结果分析下,这里分两种状况:

  • 在开启指针压缩的状况下,markword占用4字节,classpoint占用8字节,Interface data无数据,总共是12字节,因为对象须要为8的整数倍,Padding会补充4个字节,总共占用16字节的存储空间。

  • 在没有指针的状况下,markword占用8字节,classpoint占用8字节,Interface data无数据,总共是16字节。

结语

   今天的文章和你们介绍了一个对象的建立过程,从它的出生到死亡,都经历了什么?也和你们详细的说明了对象的内存布局,深刻解剖了一下对象的身体构造,这下面试官再问你,可就有的聊了,这篇文章的内容仍是比较肝的,须要你们认真阅读一下,固然,也能够关注个人公众号'moon聊技术',私下联系我,我是moon,下期见~

相关文章
相关标签/搜索