【Java面试】JVM汇总

目录

1.JVM为什么能跨平台?

2.JVM由哪些部分构成?每个部分起到什么作用?

3.什么是双亲委派?双亲委派的两大作用是什么?

举个例子🌰:

为什么要有这种"家族规矩"?

破坏双亲委派的场景(进阶了解)

4.Tomcat为什么要自定义类加载器?

5.程序计数器的作用是什么?

6.虚拟机栈(Java方法栈、JVM栈)的作用是什么?

7.堆的作用是什么?

8.GC如何判断对象是否可回收?

9.垃圾回收算法有哪些?

10.常见的垃圾收集器有哪些?


1.JVM为什么能跨平台?

Java 代码被编译成与操作系统无关的字节码 ,而 JVM 会将这些字节码解释为机器码 ,最终实现**"一次编译,到处运行"**------开发者无需针对不同平台修改代码或重新编译,只需在不同的操作系统中安装对应的 JVM 即可。

2.JVM由哪些部分构成?每个部分起到什么作用?

  1. 类加载 :类加载器将 .class 文件加载到方法区。
  2. 内存分配:对象实例在堆中分配,方法调用栈帧在JVM栈(虚拟机栈/Java方法栈)中创建。
  3. 执行代码:解释器或JIT执行字节码,程序计数器跟踪执行位置。
  4. 垃圾回收:GC自动回收堆中无用的对象。
  5. 本地调用:通过JNI调用操作系统功能(如网络、文件操作)。

3.什么是双亲委派?双亲委派的两大作用是什么?

双亲委派 就像你家里有一个"家族规矩":孩子遇到问题,先找爸妈解决,爸妈搞不定再找爷爷奶奶,谁有能力解决谁上,绝不自己瞎折腾。在Java里,这就是类加载器(ClassLoader)加载类的规则

举个例子🌰:

假设你要加载一个类(比如 java.lang.String),流程是这样的:

  1. 你(App类加载器)

    👉 先问你的"爸爸"Ext类加载器 :"你能加载这个类吗?"

    👨 Ext类加载器 又转头问他的"爸爸"Bootstrap类加载器 :"你能加载吗?"

    👴 Bootstrap类加载器 (家族最牛大佬)一看:"哦,这是JDK核心类啊,我来!" → 成功加载

  2. 如果是你写的类(比如 com.example.MyClass):

    👉 Bootstrap 说:"这我不认识,让儿子Ext试试。"

    👨 Ext类加载器 也摇头:"这也不是我的活。"

    👦 最后回到 你(App类加载器) :"好吧,我来加载!" → 成功加载你的类

  3. 如果有人想捣乱(比如自己写一个 java.lang.String):

    👉 Bootstrap 一看名字是 java.lang.String,直接加载JDK自带的,根本不会给你机会加载自己的版本 → 防止核心类被篡改

为什么要有这种"家族规矩"?

  1. 避免类的重复加载

    比如你和你爸都买同一本书,纯属浪费。双亲委派确保一个类只加载一次,全家共享。

  2. 防止核心API被篡改

    JDK的核心类(如 java.lang.*)必须由Bootstrap类加载器加载,防止你写个恶意类替换掉它们。

  3. 分工明确

    • Bootstrap :加载JDK核心类(rt.jar等)。
    • Ext :加载扩展库(jre/lib/ext下的jar包)。
    • App :加载你写的代码(classpath下的类)。

破坏双亲委派的场景(进阶了解)

有些特殊情况会打破这个规矩,比如:

  • Tomcat:每个Web应用用自己的类加载器,防止不同应用的类冲突。
  • JDBC:用线程上下文类加载器加载不同厂商的驱动。

总结:双亲委派就是"先问爸妈,不行再自己干"。

4.Tomcat为什么要自定义类加载器?

Tomcat自定义类加载器主要是为了实现Web应用隔离 (防止不同应用的同名类冲突)、支持热部署 (动态替换类文件无需重启),同时通过优先加载应用私有类打破双亲委派(保证应用独立性),但核心类仍委派父加载器加载以确保安全,最终满足多应用共存时的灵活性与稳定性需求。

5.程序计数器的作用是什么?

程序计数器是线程私有的内存区域,用于记录当前线程正在执行的字节码指令地址,确保线程切换后能准确恢复到执行位置。

6.虚拟机栈(Java方法栈、JVM栈)的作用是什么?

虚拟机栈核心作用有三点:

第一,管理方法调用的栈帧,存储方法执行时的局部变量和中间结果;

第二,通过线程独立的栈结构隔离不同线程的执行状态;

第三,控制方法调用深度,避免无限递归导致内存溢出。

7.堆的作用是什么?

堆是JVM中最重要的一块区域,所有的对象和数组被创建后都会存放在堆中,在执行字节码指令时,会把创建的对象存入堆中,对象对应的引用地址存入虚拟机栈中的栈帧中,不过当方法执行完之后,刚刚所创建的对象并不会立马被回收,而是要等JVM后台执行GC后,对象才会被回收。

8.GC如何判断对象是否可回收?

通过可达性分析,从GC Roots出发,未被引用的对象标记为可回收。

9.垃圾回收算法有哪些?

  • 标记-清除(Mark-Sweep) :标记存活对象,清除未标记对象(简单但碎片化)。
  • 复制算法(Copying) :将存活对象复制到另一块内存(适用于年轻代,无碎片但空间浪费)。
  • 标记-整理(Mark-Compact) :标记存活对象后整理到内存一端(适用于老年代,解决碎片问题)。
  • 分代收集(Generational) :结合上述算法,只是一种理念而不是具体算法,年轻代用复制,老年代用标记-清除或标记-整理。

老年代存放长期存活的对象。

10.常见的垃圾收集器有哪些?

CMS和G1的区别?

  • CMS:以最短停顿时间为目标,采用标记-清除算法,存在内存碎片问题。
  • G1:将堆划分为2048个Region,分了Eden区、S0区、S1区、老年代。

CMS和G1的核心区别在于设计目标与实现机制。CMS通过并发标记清除实现低延迟,但存在内存碎片和Full GC风险,适合小堆且对延迟敏感的场景;G1将堆划分为Region,通过Mixed GC(预测模型)在可控停顿时间内平衡吞吐量,适合大堆和稳定延迟需求。从JDK9开始,G1已成为默认回收器,而CMS已逐步淘汰。

相关推荐
高林雨露2 分钟前
Java对比学习Kotlin的详细指南(一)
java·学习·kotlin
uhakadotcom4 分钟前
Caddy Web服务器初体验:简洁高效的现代选择
前端·面试·github
uhakadotcom24 分钟前
NVIDIA Resiliency Extension(NVRx)简介:提高PyTorch训练的容错性
算法·面试·github
专业抄代码选手35 分钟前
【JS】instanceof 和 typeof 的使用
前端·javascript·面试
雷渊41 分钟前
深入分析mybatis中#{}和${}的区别
java·后端·面试
亦是远方1 小时前
2025华为软件精英挑战赛2600w思路分享
android·java·华为
花月C1 小时前
Spring IOC:容器管理与依赖注入秘籍
java·开发语言·rpc
ylfhpy1 小时前
Java面试黄金宝典22
java·开发语言·算法·面试·职场和发展
风象南2 小时前
Spring Boot 实现文件秒传功能
java·spring boot·后端
橘猫云计算机设计2 小时前
基于django优秀少儿图书推荐网(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·python·小程序·django·毕业设计