欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > 【Java面试】JVM汇总

【Java面试】JVM汇总

2025/3/1 9:29:00 来源:https://blog.csdn.net/m0_75276797/article/details/145906606  浏览:    关键词:【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已逐步淘汰。 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词