美团JVM面试题

news/2024/4/19 11:24:12/文章来源:https://blog.csdn.net/ruipeng250/article/details/131539800

1. 请解释一下对象创建的过程?

Java对象创建的过程主要分为以下五个步骤:

  • 类加载检查
    Java虚拟机在读取一条new指令时候,首先检查能否在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否被加载、解析和初始化。如果没有,则会先执行相应的类加载过程。

  • 内存分配
    在通过类加载检查后,则开始为新生的对象分配内存。该对象所需的内存大小在类加载完成后便可确定,因此为每个对象分配的内存大小是确定的。

     而分配方式主要有两种,分别为:(1)指针碰撞应用场合:堆内存规整(通俗的说就是用过的内存被整齐充分的利用,用过的内存放在一边,没有用过的放在另外一边,而中间利用一个分界值指针对这两边的内存进行分界,从而掌握内存分配情况)。即在开辟内存空间时候,将分界值指针往没用过的内存方向移动向应大小位置即可)。将堆内存这样划分的代表的GC收集器算法有:Serial,ParNew(2)空闲列表应用场合;堆内存不规整(虚拟机维护一个可以记录内存块是否可以用的列表来了解内存分配情况)即在开辟内存空间时候,找到一块足够大的内存块分配给该对象即可,同时更新记录列表。将堆内存这样划分的代表的GC收集器算法有:CMS
    
  • 初始化默认值
    在分配内存完成后,紧接着,虚拟机需要将分配到的内存空间都进行初始化(即给一些默认值),这样做是为了保证对象实例的字段在Java代码中可以在不赋初值的情况下使用。程序可以访问到这些字段对应数据类型的默认值。

  • 设置对象头
    初始化默认值完成后,虚拟机对对象进行一些简单设置,如标记该对象是哪个类的实例,这个对象的Hash码,该对象所处的年龄段等等(这些可以理解为对象实例的基本信息)。这些信息被写在对象头中。JVM根据当前的运行状态,会给出不同的设置方式。

  • 执行初始化方法
    在设置对象头完成后,最后执行由开发人员编写的对象的初始化方法,把对象按照开发人员的设计进行初始化,一个对象便创建出来了。

2. DCL(Double Check Lock)单例需不需要加volatile?

答: 需要添加volatile,否则可能会获取到半初始化对象从而引发程序未知错误!
单例对象用上volatile关键字,他的作用就是: 禁止指令重排序!


public class Singleton01 {public int total = 10;private static volatile Singleton01 instance;private Singleton01(){}public static Singleton01 getInstance(){if(instance == null){//Double Check Locksynchronized (Singleton01.class){if(instance == null){try {Thread.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}instance =  new Singleton01();}}}return  instance;}public static void main(String[] args) {for (int i = 0; i < 1000; i++) {Singleton01 instance1 = Singleton01.getInstance();System.out.println(instance1.hashCode());}}
}

扩展知识:

  1. volatile的作用
    volatile只能用来修饰成员变量,它有两大特性:可见性、有序性,此处的有序性区别于synchornized的有序性。synchornized的有序性指的是多个线程要有序地执行临界区的代码,而volatile的有序性指的是指令有序性(指令不可重排)。
  2. 什么是指令重排序?
    指令重排序是指在运行程序时,处理器为了优化性能,代码的执行顺序可能不会按代码的顺序执行,比如前后两个赋值指令,第一条需要去磁盘读取数据,第二条需要去内存读取数据,程序在执行的时候可能会在去磁盘读取数据的时候先把第二条赋值指令执行完,等从磁盘读完数据再执行第一条赋值指令,这就叫指令重拍序,而volatile保证的有序性即防止指令重排。
    3.指令重排发生的条件?
    不影响单线程的最终一致性,也就是说,在单个线程内,两条指令变换顺序,不会影响最终结果,那么处理器可能会因为性能考虑指令重排,比如两条单纯赋值的指令

3.对象在内存中的存储布局?(对象和数组的存储不同)

对象在堆内存中的存储布局可以划分为三个部分:

  • 对象头(Header)
    HotSpot虚拟机对象的对象头部分包括三类信息:
    第一类(Mark Word)是用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等;
    另外一部分(Class Pointer)是类型指针,即对象指向它的类型元数据的指针。
    数组长度: 只有数组对象才有,在32位或者64位JVM中,长度都是32bit。

  • 实例数据(Instance Data)
    对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录起来。

  • 对齐填充(Padding)
    对齐填充仅仅起着占位符的作用,将对象补齐到8字节的整数倍。
    由于虚拟机要求对象起始地址必须是8字节的整数倍,所以后面有几个字节用于把对象的大小补齐至8字节的整数倍,没有特别的功能,对齐填充不是必须存在的,仅仅是为了字节对齐。

为什么必须是8个字节?

根据“计算机组成原理”,8个字节是计算机读取和存储的最佳实践。

在这里插入图片描述

4. 对象头具体包括什么?

Java对象的对象头由三部分组成:

  • Mark Word
    MarkWord用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、同步锁信息、偏向锁标识等等。Mark Word在32位JVM中的长度是32bit,在64位JVM中长度是64bit。

通常我们都是使用的64位的JVM,Mark Word 在64位 JVM 中内部结构如下图:
在这里插入图片描述

  • 类型指针
    类型指针指向对象的类元数据,虚拟机通过这个指针确定该对象是哪个类的实例。Java对象的类数据保存在方法区。

  • 数组长度(只有数组对象才有)
    如果对象是一个数组,那么对象头还需要有额外的空间用于存储数组的长度。如果对象是数组类型,因为JVM虚拟机可以通过Java对象的元数据信息确定Java对象的大小,但是无法从数组的元数据来确认数组的大小,所以用一块来记录数组长度。

5. 对象怎么定位?

比如:T t = new T(); 如何通过引用变量t 去 找到T的实例。
JVM的执行过程,其实是有两种方式的, (1)直接应用 和(2)句柄方式.

  • 直接引用
    优点: 直接访问
    缺点: GC需要移动对象的时候稍微麻烦
    在这里插入图片描述

  • 句柄方式
    优点: 对象小,垃圾回收时不用频繁改动t
    缺点: 两次访问
    在这里插入图片描述

6.对象怎么分配?

在这里插入图片描述
扩展知识:

  1. TLAB
    TLAB (Thread Local Allocation Buffer,线程本地分配缓冲区)是 Java 中内存分配的一个概念,它是在 Java 堆中划分出来的针对每个线程的内存区域,专门在该区域为该线程创建的对象分配内存。它的主要目的是在多线程并发环境下需要进行内存分配的时候,减少线程之间对于内存分配区域的竞争,加速内存分配的速度。TLAB 本质上还是在 Java 堆中的,因此在 TLAB 区域的对象,也可以被其他线程访问。

如果没有启用 TLAB,多个并发执行的线程需要创建对象、申请分配内存的时候,有可能在 Java 堆的同一个位置申请,这时就需要对拟分配的内存区域进行加锁或者采用 CAS 等操作,保证这个区域只能分配给一个线程。

启用了 TLAB 之后(-XX:+UseTLAB, 默认是开启的),JVM 会针对每一个线程在 Java 堆中预留一个内存区域,在预留这个动作发生的时候,需要进行加锁或者采用 CAS 等操作进行保护,避免多个线程预留同一个区域。一旦某个区域确定划分给某个线程,之后该线程需要分配内存的时候,会优先在这片区域中申请。这个区域针对分配内存这个动作而言是该线程私有的,因此在分配的时候不用进行加锁等保护性的操作。

  1. 逃逸分析
    逃逸分析,是一种可以有效减少Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上
    在计算机语言编译器优化原理中,逃逸分析是指分析指针动态范围的方法,它同编译器优化原理的指针分析和外形分析相关联。当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他过程或者线程所引用,这种现象称作指针(或者引用)的逃逸(Escape)。

经过逃逸分析之后,可以得到三种对象的逃逸状态。

  • GlobalEscape(全局逃逸), 即一个对象的引用逃出了方法或者线程。例如,一个对象的引用是复制给了一个类变量,或者存储在在一个已经逃逸的对象当中,或者这个对象的引用作为方法的返回值返回给了调用方法。
  • ArgEscape(参数级逃逸),即在方法调用过程当中传递对象的应用给一个方法。这种状态可以通过分析被调方法的二进制代码确定。
  • NoEscape(没有逃逸),一个可以进行标量替换的对象。可以不将这种对象分配在传统的堆上。

编译器可以使用逃逸分析的结果,对程序进行一下优化。
a. 堆分配对象变成栈分配对象。一个方法当中的对象,对象的引用没有发生逃逸,那么这个方法可能会被分配在栈内存上而非常见的堆内存上。
b.消除同步。线程同步的代价是相当高的,同步的后果是降低并发性和性能。逃逸分析可以判断出某个对象是否始终只被一个线程访问,如果只被一个线程访问,那么对该对象的同步操作就可以转化成没有同步保护的操作,这样就能大大提高并发程度和性能。
c.矢量替代。逃逸分析方法如果发现对象的内存存储结构不需要连续进行的话,就可以将对象的部分甚至全部都保存在CPU寄存器内,这样能大大提高访问速度。

7.Object o = new Object(); 在内存中占用几个字节?

如果jvm没开启CompressedClassPointers类型指针压缩,那么首先new Object()占用8(markword)+8(class pointer)+0(instance data)+0(补齐为8的倍数)16个字节

8.为什么hotsport不使用C++对象来代表java对象?

因为C++对象有一个virtual table 这个是java对象所不需要也没有的。会占用内存

9.Class对象是在堆中还是在方法区中?

Class对象是存放在堆中
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_331275.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#开发的OpenRA游戏之维修按钮

C#开发的OpenRA游戏之维修按钮 前面分析物品的变卖按钮,如果理解这个流程,再看其它按钮的流程,其实是一样的,所以前面的文章是关键,只有理解通透的基础之上,才能继续往下。 维修按钮的存在价值,就是当建筑物受到敌方破坏,还没有完全倒掉之前,可以使用金币来进行修理。…

快速排序的非递归实现、归并排序的递归和非递归实现、基数排序、排序算法的时间复杂度

文章目录 快速排序的非递归三数取中法选取key快速排序三路划分 归并排序的递归归并排序的非递归计数排序稳定性排序算法的时间复杂度 快速排序的非递归 我们使用一个栈来模拟函数的递归过程&#xff0c;这里就是在利用栈分区间。把一个区间分为 [left,keyi-1][key][keyi1,right…

Android 进程与进程之间的通信--AIDL详细教程,以传递对象为例,两个app实现

我这里案例是 通过 IPC 传递对象 &#xff08;以DemoBean类为例&#xff09; 如下&#xff1a; AIDL 使用一种简单语法&#xff0c;允许您通过一个或多个方法&#xff08;可接收参数和返回值&#xff09;来声明接口。参数和返回值可为任意类型&#xff0c;甚至是 AIDL 生成的其…

如何将jar 包下载到自定义maven仓库

下载命令 mvn install:install-file -Dfileartifactid-version.jar -DgroupIdgroupid -DartifactIdartifactid -Dversionversion -Dpackagingjar -DlocalRepositoryPath. -DcreateChecksumtrue参数解释 在上述命令中&#xff0c;需要替换以下参数&#xff1a; artifactid-vers…

计算机组成原理课程设计 报告

在我的博客查看&#xff1a;https://chenhaotian.top/study/computer-composition-principles-course-design/ 计算机组成原理课程设计 报告 一、目的和要求 深入了解计算机各种指令的执行过程&#xff0c;以及控制器的组成&#xff0c;指令系统微程序设计的具体知识&#xf…

【前端知识】React 基础巩固(二十六)——Portals 的使用

React 基础巩固(二十六)——Portals 的使用 Portals 通常&#xff0c;组件会渲染到 root 节点下。可使用 Portals 将组件渲染至其他节点。 添加 id 为 more、modal 的 div 元素 <div id"root"></div> <div id"more"></div> &l…

工作:三菱PLC之CC-Link IE Field Network通讯知识及应用

工作&#xff1a;三菱PLC之CC-Link IE Field Network通讯知识及应用 一、理论 1. 简介连接 CC-LINK-IE通讯分别有 CC-Link IE TSN&#xff0c;CC-Link IE Control Network&#xff0c;CC-Link IE Field Network&#xff0c;CC-Link IE Field Network Basic几种形式&#xff…

成功解决wget下载报错 : wget HTTP request sent, awaiting response... 403 Forbidden

成功解决wget下载报错 : wget HTTP request sent, awaiting response... 403 Forbidden 问题描述解决方案原理什么是User Agent解决 问题描述 –2023-07-15 02:32:57-- https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2023.03-Linux-x86_64.sh Resolving mi…

PyTorch: 池化-线性-激活函数层

文章和代码已经归档至【Github仓库&#xff1a;https://github.com/timerring/dive-into-AI 】或者公众号【AIShareLab】回复 pytorch教程 也可获取。 文章目录 nn网络层-池化-线性-激活函数层池化层最大池化&#xff1a;nn.MaxPool2d()nn.AvgPool2d()nn.MaxUnpool2d()线性层激…

linux 下如何安装 tar.gz包

linux 下如何安装 tar.gz包 解压缩进入解压后的文件目录下 解压缩 tar -zxvf pycharm-community-2023.1.3.tar.gz进入解压后的文件目录下 ./pycharm.sh可执行Pycharm 建议将目录转移到其他位置 我习惯使用2020版本的 下载地址

源码阅读: echo 回显程序

文章目录 1. 目的2. 原始代码3. 化简和跨平台支持4. 修改后代码的代码分析5. References 1. 目的 阅读 netbsd 9.3 的 echo.c, 练习 C 语言源码阅读的技能。 2. 原始代码 https://github.com/NetBSD/src/blob/trunk/bin/echo/echo.c /* $NetBSD: echo.c,v 1.23 2021/11/16 …

2023年Java最新面试题

由【后端面试题宝典】提供 和 equals 的区别是什么&#xff1f; 对于基本类型&#xff0c;比较的是值&#xff1b;对于引用类型&#xff0c;比较的是地址&#xff1b;equals不能用于基本类型的比较&#xff1b;如果没有重写equals&#xff0c;equals就相当于&#xff1b;如果重…

基于JavaSwing+Mysql的仓库销售管理系统

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88049275 JDK1.8 MySQL5.7 功能&#xff1a;管理员与员工两个角色登录&#xff0c;基础数据查找&#xff0c;仓库查找&#xff0c;增删改查仓库信息、商品等 源码数据库文件配置文件课程设…

5分钟构建电商API接口服务 | python小知识

1. 什么是API 我们经常会使用一些API接口来完成特定的功能&#xff0c;比如查询天气的数据&#xff0c;下载股票的数据&#xff0c;亦或是调用ChatGPT模型的结构等等。 API全称是Application Programming Interface&#xff0c;即应用程序接口&#xff0c;它通常提供了一个功…

Mysql单表多表查询练习

题目要求&#xff1a; 1.查询student表的所有记录 2.查询student表的第2到4条记录 3.从student表查询所有的学生的学号&#xff08;id&#xff09;&#xff0c;姓名&#xff08;name&#xff09;&#xff0c;和院系&#xff08;department&#xff09;的信息 4.从student表…

SpringAMQP - 消息传输时,如何提高性能?解决 SQL 注入问题?

目录 一、问题背景 二、从消息转化器根源解决问题 1.引入依赖 2.在服务生产者和消费者中都重新定义一个 MessageConverter&#xff0c;注入到 Spring 容器中 一、问题背景 在SpringAMQP的发送方法中&#xff0c;接收消息的类型是Object&#xff0c;也就是说我们可以发送任意…

用 GPU 并行环境 Isaac Gym + 强化学习库 ElegantRL:训练机器人Ant,3小时6000分,最高12000分

前排提醒,目前我们能 “用 ppo 四分钟训练 ant 到 6000 分”,比本文的 3 小时快了很多很多,有空会更新代码 https://blog.csdn.net/sinat_39620217/article/details/131724602 介绍了 Isaac Gym 库 如何使用 GPU 做大规模并行仿真,对环境模块提速。这篇帖子,我们使用 1 …

class文件反编译成Java文件

下载jad158g.win压缩包解压到指定的磁盘下&#xff08;下载目录&#xff1a;https://varaneckas.com/jad/&#xff09; 操作命令&#xff1a;jad -o -r -s java -d src classes/**/*.class 此处src为生成Java文件存放的文件夹&#xff0c;classes则为需要转化成Java的class文件…

docker 里面各种 command not found 总结

一、ip&#xff1a;command not found 执行命令&#xff1a; apt-get update & apt-get install -y iproute2 二、yum&#xff1a;command not found 执行命令&#xff1a; apt-get update & apt-get install -y yum 三、ping&#xff1a;command not found 执行命…

Openlayers实战:多地图底图切换

在实际的地图项目中,不管是我们看到的百度地图还是高德地图等,都会有地图切换这一项。 在Openlayers实战中,我们用三种地图做demo,分别是谷歌地图。Openstreetmap,stamen地图。 切换的主要原则是设置三个底图层,设定其显示状态,用到了visible这一个属性。 效果图 源代码…