【面试题】JVM部分[2025/1/13 ~ 2025/1/19]

JVM部分[2025/1/13 ~ 2025/1/19]

  • 1. JVM 由哪些部分组成?
  • 2. Java 的类加载过程是怎样的?
  • 3. 请你介绍下 JVM 内存模型,分为哪些区域?各区域的作用是什么?
  • 4. JVM 垃圾回收调优的主要目标是什么?
  • 5. 如何对 Java 的垃圾回收进行调优?
  • 6. 常用的 JVM 配置参数有哪些?
  • 7. Java 中常见的垃圾收集器有哪些?
  • 8. 垃圾收集算法
  • 9. 线上 CPU 飙高如何排查?
  • 10. 怎么分析 JVM 当前的内存占用情况?
  • 11. OOM 后怎么分析?

我的博客地址

1. JVM 由哪些部分组成?

  1. 组成
    • 类加载器子系统(ClassLoader)
    • 运行时数据区(Runtime Data Area)
    • 执行引擎(Execution Engine)
    • 本地方法接口(Native Interface,JNI)
  2. 执行流程
    首先需要准备编译好的 Java 字节码文件(即class文件)。
    然后需要先通过一定方式(类加载器)将 class 文件加载到内存中(运行时数据区)。
    又因为字节码文件是 JVM 定义的一套指令集规范,底层操作系统无法直接执行。
    因此需要特定的命令解释器(执行引擎)将字节码翻译成特定的操作系统指令集交给 CPU 去执行。
    这个过程中会需要调用到一些不同语言为 Java 提供的接口(例如驱动、地图制作等),这就用到了本地方法接口(Native Interface)。

2. Java 的类加载过程是怎样的?

  1. 加载: 将二进制流读入内存中,为了生成一个 Class 对象。
  2. 链接
    a. 验证: 主要是验证加载进来的二进制流是否符合一定格式,是否规范,是否符合当前 JVM 版本等等之类的验证。
    b. 准备: 为静态变量(类变量)赋初始值,也即为它们在方法区划分内存空间。这里注意是静态变量,并且是初始值,比如 int 的初始值是 0。
    c. 解析: 将常量池的符号引用转化成直接引用

    符号引用可以理解为只是个替代的标签,比如你此时要做一个计划,暂时还没有人选,你设定了个 A 去做这个事。然后等计划真的要落地的时候肯定要找到确定的人选,到时候就是小明去做一件事。解析就是把 A(符号引用) 替换成小明(直接引用)。符号引用就是一个字面量,没有什么实质性的意义,只是一个代表。
    直接引用指的是一个真实引用,在内存中可以通过这个引用查找到目标。

  3. 初始化: 这时候就执行一些静态代码块,为静态变量赋值,这里的赋值才是代码里面的赋值,准备阶段只是设置初始值占个坑。

3. 请你介绍下 JVM 内存模型,分为哪些区域?各区域的作用是什么?

  1. 程序计数器(Program Counter Register):每个线程都有自己的程序计数器,用于指示当前线程执行的字节码指令的行号,以便线程执行时能够回到正确的位置。
  2. 虚拟机栈(JVM Stack):也称为 Java 方法栈,用于存储方法执行时的局部变量表、操作数栈、动态链接、方法出口等信息。每个线程在执行一个方法时,都会为该方法分配一个栈帧,并将该栈帧压入虚拟机栈,当方法执行完毕后,虚拟机会将其出栈。
  3. 本地方法栈(Native Method Stack):与虚拟机栈类似,用于存储本地方法的执行信息。
  4. (Heap):用于存放所有线程共享的对象和数组,是垃圾回收的主要区域。
  5. 方法区(Method Area):用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区也是被所有线程共享的。方法区具体实现永久代/元空间

程序计数器、虚拟机栈、本地方法栈是线程私有的,堆、方法区、运行时常量池是线程共享的。

4. JVM 垃圾回收调优的主要目标是什么?

GC 调优的核心思路就是尽可能的使对象在年轻代被回收,减少对象进入老年代。

  1. 吞吐量调优:主要关注降低垃圾回收的总时间,通过 Parallel Scavenge 和 Parallel Old 提高 CPU 使用效率。
  2. 延迟调优:关注最大停顿时间,通过 CMS、G1、ZGC 等收集器降低 STW 停顿时间。
  3. 堆大小调优:通过合理的堆内存分配和分代比例调优,避免频繁的 Minor GC 和 Full GC。

5. 如何对 Java 的垃圾回收进行调优?

  1. 思路
    分析Young GC 和 Full GC 触发频率、原因、晋升的速率、老年代内存占用量, 可以使用命令(jstat -gc [pid] [频率] [总次数])或监控页面查看
    例如: 如果发现频繁会产生 Full GC,分析日志之后发现没有内存泄漏,只是 Young GC 之后会有大量的对象进入老年代,然后最终触发 Ful GC。所以就能得知是 Survivor 空间设置太小,导致对象过早进入老年代,因此调大 Survivor 。

6. 常用的 JVM 配置参数有哪些?

  • -Xms:初始化堆内存大小
  • -Xmx:最大堆内存大小
  • -Xss:设置每个线程的栈大小
  • -XX:MetaspaceSize:初始化元空间大小
  • -XX:MaxMetaspaceSize:最大元空间大小
  • -XX:+HeapDumpOnOutOfMemoryError:当发生 OutOfMemoryError 时,生成堆转储(heap dump)文件
  • -XX:HeapDumpPath: 生成堆转储文件路径
  • -XX:+PrintGCDetails:打印详细的垃圾回收日志
  • -XX:+UseG1GC:启用G1垃圾收集器
  • -XX:+UseConcMarkSweepGC:启用CMS垃圾收集器
  • -XX:+UseZGC:启用ZGC(低延迟垃圾收集器)

7. Java 中常见的垃圾收集器有哪些?

  1. 新生代垃圾收集器
    • 1)Serial 收集器:
      • 单线程收集器,适合小型应用和单处理器环境。
      • 触发 Stop-The-World(STW)操作,所有应用线程在 GC 时暂停。
      • 适用场景:适用于单线程应用和客户端模式。
    • 2)ParNew 收集器:
      • 是 Serial 收集器的多线程版本,能够并行进行垃圾收集。
      • 与 CMS 收集器配合使用时,通常会选择 ParNew 收集器作为新生代收集器。
      • 适用场景:适用于多处理器环境,通常配合 CMS 收集器使用。
    • 3)Parallel Scavenge 收集器(吞吐量优先):
      • 也称为 “吞吐量收集器”,追求最大化 CPU 时间的利用率。
      • 并行处理新生代垃圾回收,适合大规模后台任务处理,注重吞吐量而非延迟。
      • 适用场景:适用于大规模运算密集型后台任务,适合对吞吐量要求较高的场景。
  2. 老年代垃圾收集器:
    • 1)Serial Old 收集器:
      • Serial 收集器的老年代版本,使用标记-整理(Mark-Compact)算法进行垃圾回收。
      • 适用场景:适合单线程环境和低内存使用场景,通常配合 Serial 收集器一起使用。
    • 2)Parallel Old 收集器:
      • Parallel Scavenge 收集器的老年代版本,使用多线程并行标记-整理算法。
      • 适用场景:适合大规模并行计算的场景,适用于高吞吐量要求的任务。
    • 3)CMS(Concurrent Mark-Sweep)收集器:
      • 并发标记-清除收集器,追求低延迟,减少 GC 停顿时间。
      • 使用并发标记和清除算法,适合对响应时间有较高要求的应用。
      • 缺点:可能会产生内存碎片,并且在并发阶段可能会发生 Concurrent Mode Failure,导致 Full GC。
      • 适用场景:适用于对响应时间要求高的应用,如 Web 服务和电商平台。
    • 4)G1(Garbage First)收集器:
      • 年轻代采用类似于传统的复制算法, 老年代采用标记整理算法
      • 设计用于取代 CMS 的低延迟垃圾收集器,能够提供可预测的停顿时间。
      • 通过分区来管理内存,并在垃圾收集时优先处理最有价值的区域,避免了 CMS 的内存碎片问题。
      • 适用场景:适合大内存、多 CPU 服务器应用,尤其在延迟和响应时间敏感的场景中表现出色。
    • 5)ZGC(Z Garbage Collector)收集器:
      • 低停顿、高吞吐量的垃圾收集器,停顿时间一般不会超过 10 毫秒。
      • 适用场景:适用于需要管理大堆内存且对低延迟要求极高的应用。

8. 垃圾收集算法

  1. 标记-清除算法(Mark-Sweep):
    • 主要用于 CMS,标记存活对象后,清除不可达对象,但容易产生内存碎片。
    • 工作原理:首先遍历堆中的对象,标记出所有的存活对象,接着清除未标记的对象。
    • 优点:实现简单,能够处理堆中的所有对象。
    • 缺点:标记和清除的过程会产生内存碎片,影响后续内存分配的效率。
  2. 标记-整理算法(Mark-Compact):
    • 用于 G1 和 Parallel Old,标记存活对象后进行整理,避免内存碎片。
    • 工作原理:首先标记出所有存活的对象,然后将存活的对象整理到一边,最后清除未标记的对象。
    • 优点:避免了内存碎片问题。
    • 缺点:整理阶段需要移动对象,会导致额外的开销。
  3. 复制算法(Copying):
    • 工作原理:将内存分成两部分,每次只使用其中一半,垃圾回收时将存活的对象从一半复制到另一半,清除原区域的所有对象(朴素的复制算法是这样的,实际使用会分为两个 survivor 和一个 eden 区)。
    • 优点:无需处理内存碎片,分配效率高。
    • 缺点:需要双倍的内存空间,浪费了一半的空间。

9. 线上 CPU 飙高如何排查?

  1. 首先确认哪个进程占用 CPU 过高,登录服务器利用 top 命令查看。
    top 命令是 Linux 下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于 Windows 的任务管理器
  2. 确认 CPU 利用率很高的进程的 PID,假设为 1234 确实是 Java 进程,则通过 top -Hp 1234 查看具体的线程。
  3. 假设得到的线程 ID 是 5678,再将线程转为十六进制。可以使用 printf "%x\n" 5678
  4. 得到十六进制的 tid 为 162e,此时在利用 jstack 1234 | grep 162e -A 100 查看具体的栈信息。
  5. 根据堆栈信息就可以定位到具体是哪行代码导致了 CPU 飙高,对应分析修复即可!

10. 怎么分析 JVM 当前的内存占用情况?

  1. 利用 jstat 监控和分析 JVM 内部的垃圾回收、内存等运行状态。可以用它来查看堆内存、非堆内存等的实时状态。使用命令 jstat -gc [pid] [频率] [总次数]
  2. 可以使用 jmap 查看, JVM 堆的详细信息(包括堆的配置、内存使用情况、GC 活动等)。\
  3. 阿里 arthas 使用
    • dashboard: 可以查看当前系统的实时数据面板。数据面板默认5秒刷新一次。可以 输入Q 后回车 或 Ctrl+C 退出dashboard命令。
    • thread: 后面加上线程ID会打印线程的栈。Arthas支持管道,可以用 thread 1 | grep ‘main(’ 查找到arthas-demo应用的main class。
    • sc: 用来查找JVM里已加载的类。例如查看名称为MathGame的类:sc -d *MathGame
    • jad: 用来反编译代码 。例如查看MathGame类的源代码:jad demo.MathGame
    • watch: 可以查看函数的参数/返回值/异常信息。例如查看MathGame类中primeFactors函数的返回值:watch demo.MathGame primeFactors returnObj ,每次函数被调用都会打印返回值,可以 输入Q 后回车 或 Ctrl+C 退出watch命令。

11. OOM 后怎么分析?

在发生 OOM 时,可以根据 jmap 得到堆转储文件(建议增加JVM启动参数,-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof,在发生 OOM 后自动生成转储文件),再导入到 MAT、VisualVM、GCeasy等工具中分析文件,找出哪些对象占用了大量的内存,再定位到具体的代码解决问题。

OOM内存泄露常见问题:

  1. 堆内存溢出(Java Heap Space)
    • Java 堆用于存放对象实例,如果创建了过多对象,或有内存泄漏导致对象无法被垃圾回收,堆内存就会耗尽。 如果有大量创建对象或集合类的场景,持续增加数据但未释放就会产生堆内存溢出。
    • 错误信息:java.lang.OutOfMemoryError: Java heap space
    • 解决方法:检查对象创建逻辑,确保及时释放无用对象,或增大堆内存大小(-Xmx 参数)。
  2. 栈内存溢出(StackOverflowError)
    • 每个线程都有独立的栈空间,栈用于存储方法调用的信息(局部变量、方法参数、返回地址等)。如果方法调用层次过深或存在无限递归,栈空间耗尽就会导致栈溢出。 常见于递归方法没有正确的退出条件、深层嵌套的方法调用场景。
    • 错误信息:java.lang.StackOverflowError
    • 解决方法:检查递归条件,优化递归算法或增加栈空间(-Xss 参数)。
  3. 方法区或元空间溢出(Metaspace / PermGen space)
    • 在 Java 8 之前,方法区被实现为永久代(PermGen),用于存放类的元数据(类信息、方法信息、常量池等)。在 Java 8 之后,永久代被替换为元空间(Metaspace),用本地内存实现。在频繁加载和卸载类的情况下(如使用大量动态生成的代理类或频繁热部署),可能导致方法区或元空间溢出。常见于使用动态代理频繁生成类、大量反射调用或频繁热部署场景。
    • 错误信息: Java 7 及之前:java.lang.OutOfMemoryError: PermGen space;Java 8 及之后:java.lang.OutOfMemoryError: Metaspace
    • 解决方法:增加元空间大小(-XX:MaxMetaspaceSize);优化代码以减少类加载和反射的频率。
  4. 直接内存溢出(Direct Buffer Memory)
    • Java NIO 使用直接内存(Direct Memory)来加快 I/O 操作,该内存不受 JVM 堆内存的限制。如果分配过多的直接内存,超过了设置的最大值,也会导致内存溢出。 常见于使用 NIO 操作 ByteBuffer 分配大量直接内存,或者 Netty 等框架中频繁使用直接内存场景。
    • 错误信息:java.lang.OutOfMemoryError: Direct buffer memory
    • 解决方法:检查直接内存的分配和释放情况,增加直接内存大小限制(-XX:MaxDirectMemorySize),或避免过多使用直接内存。
  5. 线程数过多导致的内存溢出(Unable to Create New Native Thread)
    • 每个线程都需要栈空间和一定的操作系统资源。如果创建过多线程而超出操作系统的资源限制,可能无法再创建新的线程,导致 OOM。 常见于创建大量线程或线程池大小过大。
    • 错误信息:java.lang.OutOfMemoryError: Unable to create new native thread
    • 解决方法:减少线程数,合理设置线程池的大小,避免无限制地创建新线程。
  6. GC 执行耗时过长导致的 OOM(GC Overhead Limit Exceeded)
    • 当 JVM 在垃圾回收上花费的时间过多且回收的内存不足以满足需要,JVM 会抛出 GC Overhead Limit Exceeded 错误,以避免长时间的垃圾回收循环。通常发生在堆内存接近耗尽但又无法完全释放的情况下。常见于对象频繁创建和销毁导致 GC 频繁触发,内存不足导致 GC 效率低下场景。
    • 错误信息:java.lang.OutOfMemoryError: GC overhead limit exceeded
    • 解决方法:增大堆内存,优化代码以减少短生命周期对象的创建,或调整垃圾回收策略。

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

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

相关文章

深度学习 DAY2:Transformer(一部分)

前言 Transformer是一种用于自然语言处理(NLP)和其他序列到序列(sequence-to-sequence)任务的深度学习模型架构,它在2017年由Vaswani等人首次提出。Transformer架构引入了自注意力机制(self-attention mech…

《目标检测数据集下载地址》

一、引言 在计算机视觉的广袤领域中,目标检测宛如一颗璀璨的明星,占据着举足轻重的地位。它宛如赋予计算机一双锐利的 “眼睛”,使其能够精准识别图像或视频中的各类目标,并确定其位置,以边界框的形式清晰呈现。这项技…

题解 CodeForces 1037D Valid BFS? 三种解法 C++

题目传送门 Problem - 1037D - Codeforceshttps://codeforces.com/problemset/problem/1037/Dhttps://codeforces.com/problemset/problem/1037/Dhttps://codeforces.com/problemset/problem/1037/Dhttps://codeforces.com/problemset/problem/1037/Dhttps://codeforces.com/p…

2024微短剧行业生态洞察报告汇总PDF洞察(附原数据表)

原文链接: https://tecdat.cn/?p39072 本报告合集洞察从多个维度全面解读微短剧行业。在行业发展层面,市场规模与用户规模双增长,创造大量高收入就业岗位并带动产业链升级。内容创作上,精品化、品牌化趋势凸显,题材走…

HTML<img>标签

例子 如何插入图片&#xff1a; <img src"img_girl.jpg" alt"Girl in a jacket" width"500" height"600"> 下面有更多“自己尝试”的示例。 定义和用法 该<img>标签用于在 HTML 页面中嵌入图像。 从技术上讲&#x…

故障诊断 | BWO白鲸算法优化KELM故障诊断(Matlab)

目录 效果一览文章概述BWO白鲸算法优化KELM故障诊断一、引言1.1、研究背景及意义1.2、故障诊断技术的现状1.3、研究目的与内容二、KELM基本理论2.1、KELM模型简介2.2、核函数的选择2.3、KELM在故障诊断中的应用三、BWO白鲸优化算法3.1、BWO算法基本原理3.2、BWO算法的特点3.3、…

apisix的authz-casbin

目录 1、apisix的auth-casbin官方介绍 2、casbin介绍和使用 2.1基本知识&#xff1a; 2.2使用例子 3、配置插件 4、postman调用 5、auth-casbin的坑 1、apisix的auth-casbin官方介绍 authz-casbin | Apache APISIX -- Cloud-Native API Gateway 2、casbin介绍和使用 c…

基于python+Django+mysql鲜花水果销售商城网站系统设计与实现

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育、辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

【大模型】ChatGPT 高效处理图片技巧使用详解

目录 一、前言 二、ChatGPT 4 图片处理介绍 2.1 ChatGPT 4 图片处理概述 2.1.1 图像识别与分类 2.1.2 图像搜索 2.1.3 图像生成 2.1.4 多模态理解 2.1.5 细粒度图像识别 2.1.6 生成式图像任务处理 2.1.7 图像与文本互动 2.2 ChatGPT 4 图片处理应用场景 三、文生图操…

【0x0052】HCI_Write_Extended_Inquiry_Response命令详解

目录 一、命令概述 二、命令格式及参数 2.1. HCI_Write_Extended_Inquiry_Response命令格式 2.2. FEC_Required 2.3. Extended_Inquiry_Response 三、生成事件及参数 3.1. HCI_Command_Complete 事件 3.2. Status 四、命令执行流程 4.1. 命令准备阶段(主机端) 4.2…

函数递归的介绍

1.递归的定义 在C语言中&#xff0c;递归就是函数自己调用自己 上面的代码就是 main 函数在函数主体内 自己调用自己 但是&#xff0c;上面的代码存在问题&#xff1a;main 函数反复地 自己调用自己 &#xff0c;不受限制&#xff0c;停不下来。 最终形成死递归&#xff0c;…

小白爬虫——selenium入门超详细教程

目录 一、selenium简介 二、环境安装 2.1、安装Selenium 2.2、浏览器驱动安装 三、基本操作 3.1、对页面进行操作 3.1.1、初始化webdriver 3.1.2、打开网页 3.1.3、页面操作 3.1.4、页面数据提取 3.1.5、关闭页面 ?3.1.6、综合小案例 3.2、对页面元素进行操作 3…

JDK长期支持版本(LTS)

https://blogs.oracle.com/java/post/the-arrival-of-java-23 jdk长期支持版本&#xff08;LTS&#xff09;&#xff1a;JDK 8、11、17、21&#xff1a;

三格电子——MODBUS TCP 转 CANOpen 协议网关

一、产品概述 1.1 产品用途 SG-TCP-COE-210 网关可以实现将 CANOpen 接口设备连接到 MODBUS TCP 网络中。用户不需要了解具体的 CANOpen 和 Modbus TCP 协议即可实现将 CANOpen 设备挂载到 MODBUS TCP 接口的 PLC 上&#xff0c;并和 CANOpen 设备进行 数据交互。 1.2 产品…

在离线无管理员权限的情况下为Linux配置oh-my-zsh(zsh+oh my zsh+powerlevel10k)

0. 前言 最近接触到一台离线环境下的Linux&#xff08;CentOS7&#xff09;&#xff0c;自带的终端实在过于丑陋&#xff08;tcsh&#xff09;&#xff0c;但是搜半天改zsh的教程要么要网、要么要管理员权限&#xff0c;奋而自己折腾半天记录于此以作备忘。 所需环境 一台能…

C 语言雏启:擘画代码乾坤,谛观编程奥宇之初瞰

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。* 这一课主要是让大家初步了解C语言&#xff0c;了解我们的开发环境&#xff0c;main函数&#xff0c;库…

Java - WebSocket

一、WebSocket 1.1、WebSocket概念 WebSocket是一种协议&#xff0c;用于在Web应用程序和服务器之间建立实时、双向的通信连接。它通过一个单一的TCP连接提供了持久化连接&#xff0c;这使得Web应用程序可以更加实时地传递数据。WebSocket协议最初由W3C开发&#xff0c;并于2…

C语言内存之旅:从静态到动态的跨越

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文一 动态内存管理的必要性二 动态…

气膜料仓:工业仓储的高效与安全新选择—轻空间

在工业仓储领域&#xff0c;如何实现高效、安全、环保的存储方式成为企业关注的重点。气膜料仓以其独特的无梁无柱设计和智能化功能&#xff0c;为工业仓储带来了全新的解决方案。 空间利用率高&#xff1a;无障碍的大容量仓储 气膜料仓内部无梁无柱&#xff0c;形成了完全开…

Windows FileZila Server共享电脑文件夹 映射21端口外网连接

我有这样一个使用场景&#xff0c;在外部网络环境下&#xff0c;通过手机便捷地读取存储在电脑上的视频文件。比如在外出旅行、出差&#xff0c;身边没有携带电脑&#xff0c;仅依靠手机设备&#xff0c;就能随时获取电脑里存储的各类视频&#xff0c;无论是学习资料视频、工作…