小小面试一下


前言蜜语

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

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

1.对象的创建过程

2.对象的内存布局

对象的创建过程

以下内容基于HotSpot VM 分代模型


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

  1. 一个对象new出来先判断线程栈是否能分配下
  • 如果能分配下,直接分配在栈中。
  • 如果分配不下则进行第二步。

判断该对象是否足够大

  • 如果足够大,则直接进入老年代。
  • 如果不够大,则进行第三步。

判断创建对象的线程的TLAB(本地线程缓冲区)空间是否足够

  • 如果足够,直接分配在TLAB中。
  • 如果不够,则进入Eden区中其他空间。然后进行第四步。

GC清除

  • 如果清除掉了该对象,则直接结束。
  • 如果没有清除掉对象,进行第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占用8字节,classpoint占用4字节,Interface data无数据,总共是12字节,由于对象需要为8的整数倍,Padding会补充4个字节,总共占用16字节的存储空间。

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

结语

今天的文章和大家介绍了一个对象的创建过程,从它的出生到死亡,都经历了什么?也和大家详细的说明了对象的内存布局,深入解剖了一下对象的身体构造,这下面试官再问你,可就有的聊了,这篇文章的内容还是比较肝的,需要大家认真阅读一下。

64位 内存占用大 嵌入式_懵!面试官问我:Object o = new Object() 占用了多少个字节?...相关推荐

  1. eureka自我保护时间_阿里面试官问我:到底知不知道什么是Eureka,这次,我没沉默...

    文章首发:阿里面试官问我:到底知不知道什么是Eureka,这次,我没沉默 什么是服务注册? 首先我们来了解下,服务注册.服务发现和服务注册中心的之间的关系. 举个形象的例子,三者之间的关系就好像是供货 ...

  2. cms是什么意思啊_美团面试官问我:ZGC 的 Z 是什么意思?

    本文的阅读有一定的门槛,请先了解 GC 的基本知识. 现代垃圾收集器的演进大部分都是往减少停顿方向发展. 像 CMS 就是分离出一些阶段使得应用线程可以和垃圾回收线程并发,当然还有利用回收线程的并行来 ...

  3. kafka是什么_技术面试官问:Kafka为什么速度那么快?

    Kafka的消息是保存或缓存在磁盘上的,一般认为在磁盘上读写数据是会降低性能的,因为寻址会比较消耗时间,但是实际上,Kafka的特性之一就是高吞吐率. 即使是普通的服务器,Kafka也可以轻松支持每秒 ...

  4. oracle sql 全是子查询查询速度太慢如何优化_如果面试官问你如何优化mysql分页查询,请把这篇文章甩给他!...

    在我们日常开发中,分页查询是必不可少的,可以说每干后端程序猿大部分时间都是CURD,所以分页的查询也接触的不少,你们都是怎么实现的呢?前不久的一段时间,我的一个同事突然找我寻求帮助,他说他写的sql查 ...

  5. 腾讯面试官问我Java中boolean类型占用多少个字节?我说一个,面试官让我回家等通知...

    来自:程序员乔戈里 ---------------第二天-------------- 什么是boolean类型,根据官方文档的描述[1]: boolean: The boolean data type ...

  6. 服务器负载不高 响应慢_京东面试官问我什么是负载均衡,兄弟们我这样说对嘛?...

    一.什么是负载均衡 Load balancing,即负载均衡,是一种计算机技术,用来在多个计算机(计算机集群).网络连接.CPU.磁盘驱动器或其他资源中分配负载,以达到最优化资源使用.最大化吞吐率.最 ...

  7. 岗位理解_当面试官问求职者对应聘岗位的理解情况

    虽然求职是看的是岗责是否匹配自己的经历和能力,但是很多面试官还是会问这样的问题.对于求职者来说,对岗位的理解其实就是把岗位职责背一遍,但是面试官既然问了,就要说出一些其他内容来.想回答好这个问题,就要 ...

  8. 赋值给集合_当面试官问集合遍历的删除方法时,要警惕这里有个异常陷阱

    开发中有时需要在遍历集合的同时又对集合元素进行删除操作,如何正确的删除并了解为什么很有必要. 比如: 这里会触发并发修改异常: 抛出异常原因:modCount和expectedModCount值不相等 ...

  9. linux 64位内存划分,linux 64位内存空间大小?(linux 64 bits memory space size? [closed])

    linux 64位内存空间大小?(linux 64 bits memory space size? [closed]) 在Linux 32bit中,内核占用1GB的内存,而用户空间将占用剩余的gigs ...

  10. 关于C/C++读写64位内存的实例笔记

    关于C/C++读写64位内存的实例笔记 前言 1.引入库 2.定义变量 3.实际读写操作 最后 前言 ReadProcessMemory和WriteProcessMemory这两个函数几乎是所有跨进程 ...

最新文章

  1. Redis学习笔记(八)——持久化
  2. Python必备收藏!Pycharm 常用快捷键方式!让鼠标离手操作
  3. devexpress 主从表中从主、从表行列值的获得
  4. Layui的一点小理解(上)
  5. d3 v5 api shape.line
  6. NEAT(NeuroEvolution of Augmenting Topologies)算法详解与实践(基于NEAT-Python)
  7. 一路PN码串行捕获设计--基于《通信收发信机的verilog实现与仿真》实例
  8. 强大的Git客户端:Tower for Mac
  9. 数学基础30讲:第一讲 高等数学预备知识
  10. 《仿人机器人原理与实战》一1.2 反射弧与仿人机器人设计
  11. 微信小程序实战–集阅读与电影于一体的小程序项目(二)
  12. npm安装 elementui 报错:404 Not Found - GET https://registry.npmjs.org/@vue%2fvue-loader-v15 - Not found
  13. 如何有效提高公众号文章阅读量
  14. 【云原生 | Docker 基础篇】03、Docker 阿里云镜像加速器
  15. 添加myenv至jupyter notebook kerne
  16. jitter概念理解
  17. virtual方法和abstract方法的使用(轉載)
  18. android 分享到qq黑屏,为什么我的手机打开QQ好友动态就会黑屏?
  19. Vue子传父,父传子
  20. 从创业走偏,到完成5亿元C轮融资,黑湖智造凭什么?

热门文章

  1. 基于mysql的可视化日志管理——loganalyzer
  2. redis 集群 搭建(非哨兵)
  3. 2016年物联网技术将从概念走向落地
  4. jquery18 css() : 样式的操作
  5. [转载]架构指南 : Java1.7+Eclipse luna + Maven 3.2.5 +spring 4.1.4
  6. Java多线程导致的的一个事物性问题
  7. sencha touch 2中list控件分组排序
  8. 大学生活没钱你会学习还是打工? C2 翻译有感
  9. Thinkphp3.2+ 微信小程序图片上传
  10. 有血有肉,汇报年终总结