当前位置: 首页 > news >正文

秋招后端开发面试题 - JVM底层原理


目录

  • JVM底层原理
    • 前言
    • 面试题
      • Java 对象的创建过程?
      • 什么是指针碰撞?什么是空闲列表?/ 内存分配的两种方式?
      • JVM 里 new 对象时,堆会发生抢占吗?JVM 是怎么设计来保证线程安全的?/ 内存分配并发问题?
      • 对象的内存布局?
      • 对象怎么访问定位?
      • 内存溢出和内存泄漏?
      • 能手写内存溢出的例子吗?
      • 内存泄漏可能由哪些原因导致呢?
      • 如何判断对象仍然存活?/ 如何判断对象是否死亡?
      • Java 中可作为 GC Roots 的对象有哪几种?
      • 说一下对象有哪几种引用?/ 强引用、软引用、弱引用、虚引用?
      • 什么是 Stop The World?
      • 什么是 OopMap?
      • 对象一定分配在堆中吗?有没有了解逃逸分析技术?
      • 线上服务 CPU 占用过高怎么排查?
      • 内存飙高问题怎么排查?
      • 举例栈溢出的情况?
      • 调整栈大小,就能保证不出现溢出吗?
      • 分配的栈内存越大越好吗?
      • 垃圾回收是否会涉及到虚拟机栈
      • 方法中定义的局部变量是否线程安全?
      • 静态变量和局部变量?
      • 如何判断一个常量是废弃常量?


JVM底层原理

前言

已经找到工作了,分享秋招时的笔记。祝大家都能顺利找到自己心仪的工作。


面试题

Java 对象的创建过程?

  1. 类加载检查:
    • 当虚拟机遇到 new 指令时,首先检查这个指令的参数,也就是要创建的对象的类是否已经加载过
    • 如果没有加载过,虚拟机会执行类加载过程
  2. 分配内存:
    • 类加载检查通过后,虚拟机会为新对象分配内存空间
  3. 对象内存初始化:
    • 分配内存完成后,虚拟机会将分配到的内存空间初始化为零值
  4. 设置对象头:
    • 虚拟机会在对象的内存空间中设置对象头,用于存储关于对象的元数据信息
  5. 执行初始化方法(构造函数):
    • 经过上述步骤,一个新的对象已经产生,但是从 Java 程序的角度来看,对象的创建还没有完成
    • 然后,会根据程序员定义的构造函数进行初始化

什么是指针碰撞?什么是空闲列表?/ 内存分配的两种方式?

指针碰撞:

  • 指针碰撞假定 Java 堆中的内存是绝对规整的
  • 内存的分界点由一个指针作为指示器来标示,指向已分配内存的末尾
  • 在分配对象内存时,只需要将指针向空闲空间方向移动对象内存大小的位置
  • 适用于基于压缩策略的收集器,例如 Serial 和 ParNew 收集器

空闲列表:

  • 空闲列表假设 Java 堆内存并不规整,已分配内存和空闲内存交错分布
  • 虚拟机维护一个空闲列表,记录哪些内存块是可用的,即未被分配的
  • 在分配对象内存时,虚拟机会在空闲列表中找到一块足够大的空间来分配给对象。分配后,虚拟机需要更新空闲列表上的记录,标记分配的区域为已用
  • 适用于基于清除算法的收集器,例如 CMS 收集器

JVM 里 new 对象时,堆会发生抢占吗?JVM 是怎么设计来保证线程安全的?/ 内存分配并发问题?

  • CAS:使用 CAS 操作来保证更新操作的原子性
  • 本地线程分配缓冲 (TLAB):
    每个线程在 Java 堆中预先分配一小块内存,称为本地线程分配缓冲
    要分配内存的线程,先在本地缓冲区中分配,只有本地缓冲区用完,分配新的缓冲区才需要同步锁定

对象的内存布局?

对象在堆内存中的布局可以划分为三个部分:对象头、实例数据和对齐填充

  • 对象头:包括两部分信息:存储对象自身的运行时数据;类型指针
  • 实例数据:用来存储对象真正的有效信息
  • 对齐填充:起占位符的作用

对象怎么访问定位?

使用句柄:

  • Java 堆中划分内存来作为句柄池
  • 句柄中包含对象实例数据的指针和对象类型数据的指针
    image-20230317153832919

直接指针:

  • 对象的实例数据直接存放在堆内存中
    image-20230317154017974

对比:

  • 使用句柄:在对象被移动的时候,不需要更新引用地址
  • 直接指针:效率高,节省了一次指针定位的时间开销(HotSpot 使用)

内存溢出和内存泄漏?

  • 内存溢出:申请的内存超过可用内存,内存不足
  • 内存泄漏:申请的内存空间没有被正确释放,导致内存空间被浪费

能手写内存溢出的例子吗?

  • Java 堆溢出:Java 堆用于存储对象实例,只要不断创建不可回收的对象,比如静态变量,随着对象数量的增加,总容量超过最大堆的限制就会产生 OOM
    public static void main(String[] args) {List<OOMObject> list = new ArrayList<>();while (true) {list.add(new OOMObject());}}
  • 虚拟机栈溢出:不停创建线程,也会出现 OOM 异常
    public static void recursiveMethod() {recursiveMethod();}public static void main(String[] args) {try {recursiveMethod();} catch (Throwable e) {System.out.println("Stack depth: " + e.getStackTrace().length);e.printStackTrace();}}

内存泄漏可能由哪些原因导致呢?

  • 静态集合: 静态集合生命周期与 JVM 相同,如果将对象添加到静态集合中并且忘记删除,这些对象将一直存在于内存中,无法被垃圾回收
  • 单例模式: 单例模式中的实例会被以静态变量的方式存储在内存中,一旦创建,会在整个 JVM 生命周期中存在。如果单例对象占用内存过多或者被误用,就可能导致内存泄漏
  • 连接未释放: 如果在使用完数据库连接、网络连接等资源后没有正确关闭,这些资源可能不会被释放,导致内存泄漏
  • 变量作用域过大: 如果变量的作用域超出了实际需要的范围,导致对象不能被及时释放,就会引起内存泄漏
  • hash 值发生改变: 如果对象的 hashCode 值在存入哈希容器后被修改,那么在尝试从哈希容器中获取该对象时,哈希容器会根据 hashCode 去查找,但实际上已经找不到这个对象了
  • ThreadLocal 使用不当: ThreadLocal 中的 key 是弱引用,但 value 是强引用。如果 ThreadLocal 的使用不当,导致 key 无法被垃圾回收,而 value 却一直存在,就会造成内存泄漏

如何判断对象仍然存活?/ 如何判断对象是否死亡?

引用计数算法:

  • 在对象中添加一个引用计数器
  • 每当有一个地方引用它时,计数器值就 +1
  • 引用失效时,计数器值 -1
  • 任何时刻计数器为零的对象就是不可能再被使用的
  • 不使用该方法,因为很难解决对象之间相互循环引用的问题

可达性分析算法:

  • 通过一系列 GC Roots 的对象作为起点
  • 从这些节点开始向下搜索,节点走过的路径就是引用链
  • 当一个对象到 GC Roots 没有任何引用链相连,证明此对象是不可能再被使用的
    image-20230317160832041

Java 中可作为 GC Roots 的对象有哪几种?

  • 虚拟机栈中引用的对象
  • 本地方法栈中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象

说一下对象有哪几种引用?/ 强引用、软引用、弱引用、虚引用?

强引用:

  • 使用最普遍的引用
  • 无论任何情况,只要具有强引用,垃圾收集器就永远不会回收被引用的对象

软引用:

  • 用来描述还有用,但非必须的对象
  • 只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收

弱引用:

  • 用来描述那些非必须的对象,强度比软引用还弱一些
  • 被弱引用关联的对象只能生存到下一次垃圾收集发生为止
  • 无论当前内容是否足够,都会回收掉只被弱引用关联的对象

虚引用:

  • 不会决定对象的生命周期
  • 唯一目的是为了能在这个对象被收集器回收时收到一个系统通知

什么是 Stop The World?

  • 在垃圾回收的过程中,会涉及到对象的移动。为了保证对象引用更新的正确性,必须暂停所有的用户线程,即 Stop The World

什么是 OopMap?

  • 类加载完成后,记录对象偏移量和数据类型的映射表

对象一定分配在堆中吗?有没有了解逃逸分析技术?

  • 对象不一定分配在堆中
  • 逃逸分析是一种编译器技术,用于确定对象创建后从方法逃逸到哪些位置,并确定将对象存放在堆上还是栈
  • 如果对象没有逃逸到方法的外部,可以将其存放在栈上,避免频繁的堆内存分配和垃圾回收,从而提高程序的性能

线上服务 CPU 占用过高怎么排查?

  • 首先找出哪个进程占用 CPU 过高
  • 然后找到进程中的哪个线程占用 CPU 过高
  • 找到线程 ID 后,打印出对应线程的堆栈信息
  • 根据线程的堆栈信息定位到具体代码

内存飙高问题怎么排查?

如果内存飙高发生在 Java 进程上,一般是因为创建了大量的对象,垃圾回收的速度跟不上对象创建的速度,或者是内存泄露导致对象无法回收

举例栈溢出的情况?

  • 栈溢出就是方法执行时,创建的栈帧超过了栈的深度,出现 StackOverflowError
  • 解决方法:使用参数 -Xss 调整 JVM 栈的大小
  • 具体例子:
    • 局部数组过大
    • 递归调用的层次太多。递归函数在运行时会执行压栈操作
    • 指针或数组越界。例如字符串拷贝,处理用户输入

调整栈大小,就能保证不出现溢出吗?

  • 不能
  • 如果程序是死递归的情况,调整栈的大小只是说异常出现的时间会晚一些

分配的栈内存越大越好吗?

  • 不是
  • 如果程序是死递归的情况,分配大内存的栈只是说异常出现的时间会晚一些
  • 会导致可执行的线程数减少,影响其他内存结构

垃圾回收是否会涉及到虚拟机栈

  • 不会,因为只有入栈出栈操作,出栈的过程就相当于 GC

方法中定义的局部变量是否线程安全?

  • 如果只有一个线程才可以操作此数据,则必然线程安全
  • 如果有多个线程操作此数据,则此数据是共享数据。如果不考虑同步机制,会存在线程安全问题
  • 如果变量是在方法内部产生,内部消亡的就是安全的,不是内存产生,或者作为返回值返回的(生命周期没有结束)就不是安全的

静态变量和局部变量?

  • 参数表分配完毕之后,再根据方法体内的变量顺序和作用域分配
  • 类变量表有两次初始化的机会
    • 第一次是在准备阶段,执行系统初始化,对类变量设置零值
    • 第二次是在初始化阶段,赋予程序员在代码中定义的初始值
  • 局部变量不存在系统初始化的过程,即定义了局部变量必须人为的初始化

如何判断一个常量是废弃常量?

  • 假设在字符串常量池中存在字符串 “abc”
  • 如果当前没有任何 String 对象引用该字符串常量的话,就说明常量 “abc” 就是废弃常量

秋招后端开发面试题系列目录
一、Java
1.1 Java基础上
1.2 Java基础下
1.3 Java集合
1.4 JavaIO
1.5 Java多线程上
1.6Java多线程下
二、JVM
2.1 JVM底层原理
2.2 垃圾回收器
2.3 垃圾回收算法
2.4 类加载机制
2.5 运行时数据区
三、MySQL
3.1 MySQL基础
3.2 事务
3.3 索引
3.4 锁机制
3.5 MVCC
四、Redis
4.1 Redis基础
4.2 缓存原理
五、中间件
5.1 RabbitMQ
六、Spring开源框架
6.1 Spring
6.2 Spring MVC
6.3 Spring Boot
6.4 MyBatis
七、操作系统
八、计算机网络
九、设计模式
十、微服务架构
十一、Spring Cloud分布式
11.1 分布式基础
11.2 Spring Cloud
11.3 GateWay
11.4 Nacos
11.5 OpenFeign
11.6 Ribbon
十二、算法
十三、项目

相关文章:

秋招后端开发面试题 - JVM底层原理

目录 JVM底层原理前言面试题Java 对象的创建过程&#xff1f;什么是指针碰撞&#xff1f;什么是空闲列表&#xff1f;/ 内存分配的两种方式&#xff1f;JVM 里 new 对象时&#xff0c;堆会发生抢占吗&#xff1f;JVM 是怎么设计来保证线程安全的&#xff1f;/ 内存分配并发问题…...

VUE2从入门到精通(一)

**************************************************************************************************************************************************************************** 1、课程概述 【1】前置储备&#xff1a;HTMLCSSJS、WebAPI、Ajax、Node.js 【2】1天&…...

cmake进阶:文件操作之写文件

一. 简介 cmake 提供了 file() 命令可对文件进行一系列操作&#xff0c;譬如读写文件、删除文件、文件重命名、拷贝文件、创建目录等等。 接下来 学习这个功能强大的 file() 命令。 本文学习 CMakeLists.txt语法中写文件操作。 二. cmake进阶&#xff1a;文件操作之写文件…...

ubuntu 安装单节点HBase

下载HBase mkdir -p /home/ellis/HBase/ cd /home/ellis/HBase/ wget https://downloads.apache.org/hbase/2.5.8/hbase-2.5.8-bin.tar.gz tar -xvf hbase-2.5.8-bin.tar.gz安装java jdk sudo apt install openjdk-11-jdksudo vim /etc/profileexport JAVA_HOME/usr/lib/jvm/…...

HTTP 多个版本

了解一下各个版本的HTTP。 上个世纪90年代初期&#xff0c;蒂姆伯纳斯-李&#xff08;Tim Berners-Lee&#xff09;及其 CERN的团队共同努力&#xff0c;制定了互联网的基础&#xff0c;定义了互联网的四个构建模块&#xff1a; 超文本文档格式&#xff08;HTML&#xff09; …...

【DevOps】探索Linux命令行世界:深入了解Shell的力量

目录 一、Linux Shell 详细介绍 1. Shell基础概念 2. Shell的功能特性 3. 常用Shell命令与技巧 4. 高级Shell特性与实践 二、常见的Shell及其比较 1. Bash (Bourne Again SHell) 2. Zsh (Z Shell) 3. Fish (Friendly Interactive SHell) 4. Ksh (Korn SHell) 5. Csh …...

互斥量的使用

文章目录 前言一、互斥量与二进制信号量二、优先级反转与优先级继承三、递归锁 前言 通过学习上一章互斥量理论基础&#xff0c;这一章我们来做一些实验进行验证。 一、互斥量与二进制信号量 互斥量使用和二进制信号量类似 互斥量有优先级继承功能&#xff0c;二进制信号量没有…...

关于面试真题的压迫

1.请描述一下您在使用JavaScript进行DOM操作时&#xff0c;如何提高页面性能和用户体验&#xff1f; 使用事件委托&#xff1a;在父元素上监听事件&#xff0c;而不是为每个子元素都添加事件监听器。这样可以减少事件处理程序的数量&#xff0c;提高性能。 缓存DOM查询&#x…...

1700java进销存管理系统Myeclipse开发sqlserver数据库web结构java编程计算机网页项目

一、源码特点 java web进销存管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为sqlser…...

mysql数据库(排序与分页)

目录 一. 排序数据 1.1 排序规则 1.2 单列排序 1.我们也可以使用列的别名&#xff0c;给别名进行排序 2.列的别名只能在 ODER BY 中使用&#xff0c; 不能在WHERE中使用。 3.强调格式&#xff1a;WHERE 需要在 FROM 后&#xff0c; ORDER BY 之前 1.3 二级排序&…...

Android 实时监听Activity堆栈变化(系统应用)

private val mIActivityManager: IActivityManager ActivityManagerNative.asInterface(ServiceManager.getService(Context.ACTIVITY_SERVICE)) 方式一&#xff08;registerProcessObserver&#xff09; &#xff1a; mIActivityManager.registerProcessObserver(mIProcess…...

双目深度估计原理立体视觉

双目深度估计原理&立体视觉 0. 写在前面1. 双目估计的大致步骤2. 理想双目系统的深度估计公式推导3. 双目标定公式推导4. 极线校正理论推导 0. 写在前面 双目深度估计是通过两个相机的对同一个点的视差来得到给该点的深度。 标准系统的双目深度估计的公式推导需要满足:1)两…...

Redis探索之旅(基础)

目录 今日良言&#xff1a;满怀憧憬&#xff0c;阔步向前 一、基础命令 1.1 通用命令 1.2 五大基本类型的命令 1.2.1 String 1.2.2 Hash 1.2.3 List 1.2.4 Set 1.2.5 Zset 二、过期策略以及单线程模型 2.1 过期策略 2.2 单线程模型 2.3 Redis 效率为什么这么高 三…...

C语言/数据结构——每日一题(链表的中间节点)

一.前言 今天我在LeetCode刷到了一道单链表题&#xff0c;想着和大家分享一下这道题&#xff1a;https://leetcode.cn/problems/middle-of-the-linked-list。废话不多说让我们开始今天的知识分享吧。 二.正文 1.1题目描述 1.2题目分析 这道题有一个非常简便的方法——快慢指…...

这是用VS写的一个tcp客户端和服务端的demo

服务端&#xff1a; 客户端&#xff1a; 其实这里面的核心代码就两行。 客户端的核心代码&#xff1a; //套接字连接服务端 m_tcpSocket->connectToHost(_ip,_port);//通过套接字发送数据m_tcpSocket->write(ui.textEditSend->toPlainText().toUtf8());//如果收到信…...

代码随想录算法训练营day18 | 102.二叉树的层序遍历、226.翻转二叉树、101. 对称二叉树

102.二叉树的层序遍历 迭代法 层序遍历使用队列&#xff0c;同时记录每层的个数 class Solution:def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:res []if not root:return resqueue collections.deque()queue.append(root)while queue:size len…...

工厂自动化升级改造参考(01)--设备通信协议详解及选型

以下是整合了通信协议的特点、应用场景、优缺点以及常用接口方式的描述: 以太网/IP: 来历: 以太网是一种局域网技术,由罗伯特梅特卡夫和大卫博格在1973年开发。IP是网络层协议,负责在网络中的设备间传输数据。特点:基于标准的以太网技术,使用TCP/IP协议栈,支持高速数据传…...

数据结构与算法之经典排序算法

一、简单排序 在我们的程序中&#xff0c;排序是非常常见的一种需求&#xff0c;提供一些数据元素&#xff0c;把这些数据元素按照一定的规则进行排序。比如查询一些订单按照订单的日期进行排序&#xff0c;再比如查询一些商品&#xff0c;按照商品的价格进行排序等等。所以&a…...

VSCode通过SSH连接虚拟机Ubuntu失败

问题说明 最近使用VSCode通过SSH连接Ubuntu&#xff0c;通过VSCode访问Ubuntu进行项目开发&#xff0c;发现连接失败 在VSCode中进行SSH配置 这些都没有问题&#xff0c;但在进行连接时候出现了问题&#xff0c;如下&#xff1a; 出现了下面这个弹窗 解决方法 发现当…...

在Codelab对llama3做Lora Fine tune微调

Unsloth 高效微调大模型的工具&#xff0c;通过Unsloth微调Llama3, Mistral, Gemma 速度提升2-5倍&#xff0c;内存减少70%&#xff01; Codelab 创建一个jupyter notebook 选择 T4 GPU 安装Fine tune 相关的lib %%capture import torch major_version, minor_version torch…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...