JVM面试题-JVM对象的创建过程、内存分配、内存布局、访问定位等问题详解

2023-09-19 09:05:52

对象

内存分配的两种方式

指针碰撞

适用场合:堆内存规整(即没有内存碎片)的情况下。

原理:用过的内存全部整合到一边,没有用过的内存放在另一边,中间有一个分界指针,只需要向着没用过的内存方向将该指针移动对象内存大小位置即可。

使用该分配方式的GC收集器:Serial, ParNew

空闲列表

适用场合:堆内存不规整的情况下。

原理:虚拟机会维护一个列表,列表中会记录哪些内存块是可用的,在分配的时候,找一块儿足够大的内存块儿来划分给对象实例,最后更新列表记录。

使用该分配方式的GC收集器:CMS

如何选择

选择以上两种方式中的哪一种,取决于 Java 堆内存是否规整。

而 Java 堆内存是否规整,取决于 GC 收集器的算法是"标记-清除",还是"标记-整理"(也称作"标记-压缩"),值得注意的是,复制算法内存也是规整的。

对象的创建过程

Java 对象的创建过程我建议最好是能默写出来,并且要掌握每一步在做什么。

Step1:类加载检查

虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

Step2:分配内存

类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。

Step3:初始化零值

内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。

Step4:设置对象头

初始化零值完成之后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。 这些信息存放在对象头中。 另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

Step5:执行 init 方法初始化

在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从 Java 程序的视角来看,对象创建才刚开始,<init> 方法还没有执行,所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行 <init> 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来

对象的内存布局

可以划分为三个部分:对象头、实例数据、对齐填充(8bit倍数)

  1. 虚拟机的对象头:包括两部分信息:

    1. 第一部分用于存储对象自身的运行时数据(哈希码、GC 分代年龄、锁状态标志等等)

    2. 另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

  2. 实例数据:是对象真正存储的有效信息,也是在程序中所定义的各种类型的字段内容。

  3. 对齐填充:不是必然存在的,也没有什么特别的含义,仅仅起占位作用。 因为 Hotspot 虚拟机的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,换句话说就是对象的大小必须是 8 字节的整数倍。而对象头部分正好是 8 字节的倍数(1 倍或 2 倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

对象的访问定位

对象的访问方式由虚拟机实现而定,目前主流的访问方式有:使用句柄直接指针

建立对象就是为了使用对象,我们的 Java 程序通过栈上的 reference引用 数据来操作堆上的具体对象。

句柄的方式

如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference (引用)中存储的就是对象的句柄地址。

流程就是: 引用 找到--》 句柄地址 找到--》 实际数据

句柄中包含了对象实例数据与对象类型数据各自的具体地址信息。

优点

这种方式的好处是可以使对象的布局更加灵活,因为对象数据可以在堆内存中移动而不影响句柄的引用。

缺点

访问对象需要两次内存访问:首先是根据句柄找到对象的引用,然后再根据引用找到对象的实际数据。这会导致一些额外的性能开销。

直接指针

如果使用直接指针访问,reference引用 中存储的直接就是对象的地址。

流程就是: 引用 找到--》 实际数据

指针访问方式最大的好处:就是速度快,它节省了一次指针定位的时间开销。

更多推荐

如何处理ChatGPT在文本生成中的语法错误和不合理性?

ChatGPT是一种强大的自然语言处理模型,但它并不是完美的,有时会产生语法错误或不合理的文本。这些问题可能会影响模型生成的内容的质量和可信度。在处理ChatGPT中的语法错误和不合理性时,有许多方法和策略可以采用,以下是一些详细的讨论:**1.数据清洗和预处理:**首先,可以通过对输入数据进行清洗和预处理来减少语法错

Ninja: Towards Transparent Tracing and Debugging on ARM【TEE的应用】

目录摘要引言贡献背景TrustZone和受信任的固件PMU和ETM相关工作x86上的透明恶意软件分析ARM上的动态分析工具基于仿真的系统硬件虚拟化裸机系统Trustzone相关的系统系统架构具体实现和评估可以看论文,这里不赘述了讨论总结作者:ZhenyuNingandFengweiZhang发布:USENIX时间:20

Hadoop NameNode执行命令工作流程

HadoopNameNode执行命令工作流程客户端API或者CLI与NameNode的交互命令数据的格式(1)预处理流程(2)创建NameNode与NameNodePrcServer流程(3)HDFSAPI以及CLI的命令到NameNode的工作执行流程(4)执行命令的参数流动客户端API或者CLI与NameNode的

使用LDA(线性判别公式)进行iris鸢尾花的分类

线性判别分析((LinearDiscriminantAnalysis,简称LDA)是一种经典的线性学习方法,在二分类问题上因为最早由[Fisher,1936]提出,亦称”Fisher判别分析“。并且LDA也是一种监督学习的降维技术,也就是说它的数据集的每个样本都有类别输出。这点与主成分和因子分析不同,因为它们是不考虑样

9、DVWA——XSS(Stored)

文章目录一、存储型XSS概述二、low2.1源码分析2.2通关分析三、medium3.1源码分析3.2通关思路四、high4.1源码分析4.2通关思路一、存储型XSS概述XSS,全称CrossSiteScripting,即跨站脚本攻击,某种意义上也是一种注入攻击,是指攻击者在页面中注入恶意的脚本代码,当受害者访问该页面

分布式系统中的选举,日志副本,安全等设计思想

链接:https://pan.baidu.com/s/1G9295khav7_k3dD9G0f_Kw?pwd=q216提取码:q216领导选举领导选举(Leaderelection)是在分布式系统中选择一个节点作为领导者或协调者的过程。分布式系统通常由多个节点组成,每个节点都可以执行特定的任务。然而,为了使系统有序运行

HCIE-容器docker

1、安装配置操作系统,使用CentOSstream8镜像之前:RHEL8.4发布了,CentOS紧随其后,发布CentOS8.4之后:CentOS走在前面,成为RHEL上游,再去发布RHEL制作模板,模板配置要求,cpu至少2个,内存建议4G,硬盘100G,网卡使用NAT模式。1.编辑网卡[root@tempnetwo

Java|List.subList 踩坑小记

很久以前在使用Java的List.subList方法时踩过一个坑,当时记了一条待办,要写一写这事,今天完成它。我们先来看一段代码://初始化list为{1,2,3,4,5}List<Integer>list=newArrayList<>();for(inti=1;i<=5;i++){list.add(i);}//取前3

传感器浮点数数据在串口通信中封包技术解析

一、项目实现要求根据项目要求,我们需要在多台机器人间进行数据通信,系统搭建如下:在机器人A上搭载大气压模块传感器和zigbee通信模块,在机器人B上搭载手势传感器和zigbee通信模块,在机器人C上搭载zigbee通信模块,要求A和B的传感器数据能够通过zigbee模块传输到机器人C并用以做进一步的控制处理。二、由于分

word的分隔符和分页符

目录1.word中的分隔符和分页有何不同2.word中我想把表格所在的页设置为横向,上下页均为纵向3.表格页末尾的光标回车生成新的页面后,其仍然为横向,而我希望它为纵向1.word中的分隔符和分页有何不同分隔符和分页符在Word中都是用于文本分段的工具,但它们的用途和操作方式有所不同。分隔符是一个广义的概念,包括分页符

MYSQL的锁

概述锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更

热文推荐