JVM常见面试题

一、JVM的内存区

JVM的内存区分为虚拟机栈、本地方法栈、程序计数器、堆、方法区。

其中,虚拟机栈、本地方法栈、程序计数器是每个线程独占区,堆、方法区是所有线程共享的内存区域。

虚拟机栈:每个线程在运行时都会创建一个虚拟机栈。栈中存储的是栈帧(Stack Frame),每个方法调用都会创建一个栈帧,并将其压入栈中。

特点:

  • 每个线程都有自己独立的虚拟机栈。
  • 栈帧包含局部变量表、操作数栈、动态链接、方法出口等信息。
  • 生命周期与线程相同。

**本地方法栈:**为执行本地native方法(如C/C++代码)提供支持。

特点:

  • 类似于虚拟机栈,但专门用于本地方法调用。
  • 每个线程有自己的本地方法栈。

程序计数器:记录当前线程所执行的字节码指令地址。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器值为空(Undefined)。

特点:

  • 每个线程都有自己的程序计数器。
  • 保证线程切换后能恢复到正确的执行位置

**堆:**所有对象实例以及数组都要在堆上分配

特点:

  • 垃圾回收的主要区域。
  • 可细分为年轻代(Young Generation)和老年代(Old Generation)。

方法区: 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

特点:

  • 在HotSpot虚拟机中,方法区的实现称为"永久代"(PermGen,在JDK 8之前)或"元空间"(Metaspace,在JDK 8及之后)。

**运⾏时常量池:**运行时常量池是方法区的一部分。JDK 8之前位于永久代(堆内存)中,在JDK 8及之后位于元空间(本地内存)中。

二、垃圾回收算法

1、垃圾回收的基本概念

(1)**对象可达性分析:**JVM通过一系列称为"根节点(Roots)"的对象开始,遍历所有引用链,找到所有可达的对象。所有不可达的对象被认为是垃圾,可以被回收。

(2)根节点(Roots):

  • 虚拟机栈中引⽤的对象(本地变量表)
  • 本地方法栈中引⽤的对象
  • 方法区中静态属性引⽤的对象
  • 方法区中常量引⽤的对象

2、主要的垃圾回收算法

(1)标记-清除算法:

  • 标记阶段:从根节点开始遍历所有对象,并标记所有不可达的对象。
  • 清除阶段:扫描整个堆,回收被标记的对象(即垃圾对象)。

缺点:

  • 容易产生内存碎片,导致后续分配大对象时可能失败。
  • 标记和清除过程需要遍历整个堆,效率较低。

(2)标记-整理算法

类似于标记-清除,但在清除阶段,会将存活的对象移动到堆的一端,然后清理剩余部分。

缺点:

  • 移动对象的过程较为复杂,耗时较长。

(3)复制算法

将堆分成两个区域,每次只使用一个区域,当一个区域满了,将存活的对象复制到另一个区域,并清理当前区域。

缺点:

  • 需要额外的空间来存储对象的副本。
  • 适用于年轻代(Young Generation),因为大多数对象生命周期较短。

(4)分代回收算法

基于大多数对象生命周期较短的观察,JVM将内存划分为新生代和老年代。分配的依据是对象的经历的GC次数。对象创建时,一般在新生代的Eden Space申请内存,当经历一次GC之后对象还存活,那么对象的年龄+1,当对象年龄超过一定值(默认值为 15),对象就会进入老年代,当然有足够大的对象,即使年龄未达到阈值,这些对象也可能被直接晋升到老年代,因为复制一个大对象耗时。

三、新生代和老年代的区别

对象特性:大多数新创建的对象会被分配到新生代,这些对象的生命周期通常较短,很多对象在创建后不久就不再使用,成为垃圾对象等待回收。而老年代存储的是经过多次垃圾回收仍然存活的对象。

垃圾回收算法的区别:新生代主要使用复制算法 进行垃圾回收。新生代内存被分为一个大的Eden区和两个小的Survivor区。新对象优先分配在Eden区,当Eden区满时,触发Minor GC (新生代垃圾回收),将Eden区和一个Survivor区中存活的对象复制到另一个Survivor区,然后清空Eden区和之前使用过Survivor区。经过多次Minor GC后仍存活的对象被晋升到老年代。老年代一般采用标记-清除算法 或者标记-整理算法。 老年代的垃圾回收成为Major GCFull GC

四、主要的垃圾回收机制

**Serial收集器:**新生代,单线程,简单高效,适合单核处理器和小内存环境

**ParNew收集器:**新生代,并行执行,减少停顿时间,适合多核处理器

**Parallel Scavenge收集器:**新生代,高吞吐量,减少垃圾回收时间,适合后台处理

**CMS收集器:**老年代,并发执行,减少停顿时间,适合对响应时间要求高的应用

**G1收集器:**新生代+老年代,分区管理,优先回收垃圾最多的区域,适合大堆内存和低延迟需求

相关推荐
m0_5500246310 分钟前
持续集成/持续部署(CI/CD) for Python
jvm·数据库·python
云姜.1 小时前
线程和进程的关系
java·linux·jvm
heartbeat..1 小时前
JVM 性能调优流程实战:从开发规范到生产应急排查
java·运维·jvm·性能优化·设计规范
玄同7651 小时前
SQLite + LLM:大模型应用落地的轻量级数据存储方案
jvm·数据库·人工智能·python·语言模型·sqlite·知识图谱
团子的二进制世界1 小时前
G1垃圾收集器是如何工作的?
java·jvm·算法
Max_uuc1 小时前
【C++ 硬核】打破嵌入式 STL 禁忌:利用 std::pmr 在“栈”上运行 std::vector
开发语言·jvm·c++
Serene_Dream2 小时前
JVM 并发 GC - 三色标记
jvm·面试
m0_5613596721 小时前
使用Python处理计算机图形学(PIL/Pillow)
jvm·数据库·python
HAPPY酷1 天前
构造与析构:C++ 中对象的温柔生灭
java·jvm·c++
海心焱1 天前
从零开始构建 AI 插件生态:深挖 MCP 如何打破 LLM 与本地数据的连接壁垒
jvm·人工智能·oracle