JVM 高频面试题及详细答案(实战版)_第1页
JVM 高频面试题及详细答案(实战版)_第2页
JVM 高频面试题及详细答案(实战版)_第3页
JVM 高频面试题及详细答案(实战版)_第4页
JVM 高频面试题及详细答案(实战版)_第5页
已阅读5页,还剩4页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JVM高频面试题及详细答案(实战版)一、JVM基础核心概念1、什么是JVM?它的核心作用是什么?JVM即Java虚拟机,是运行Java字节码的虚拟计算机,也是Java实现跨平台的核心基础。核心作用主要有三点:1.屏蔽操作系统、硬件差异,实现一次编译、到处运行,class字节码文件可以在任意装有JVM的环境运行;2.提供内存管理、垃圾回收、即时编译、安全校验等底层能力,降低开发者手动管理内存、优化代码的成本;3.负责加载class文件、解析字节码、执行Java程序,是Java程序运行的唯一载体。2、JDK、JRE、JVM三者的区别和关系?三者是层层包含的关系:JDK>JRE>JVM。1.JVM:核心运行环境,只负责执行字节码,无编译、开发工具,是最底层的运行核心;2.JRE:Java运行环境,包含JVM+Java核心类库,只能运行Java程序,无法开发、编译代码,普通用户运行程序只需安装JRE;3.JDK:Java开发工具包,包含JRE+编译、调试、打包等开发工具(javac、java、jmap、jstack等),是开发者编写、编译、调试程序的必备环境。3、Java程序的运行流程是什么?1.开发者编写.java源代码文件;2.通过javac编译器将源代码编译为跨平台的.class字节码文件;3.JVM的类加载器读取class字节码文件,进行加载、链接、初始化;4.JVM解释器或即时编译器将字节码翻译为操作系统可识别的机器码;5.操作系统执行机器码,运行程序,同时JVM负责内存管理、垃圾回收等后台工作。二、JVM内存结构(运行时数据区)1、JVM运行时数据区包含哪些区域?哪些是线程私有?哪些是线程共享?JVM运行时数据区分为五大区域,划分核心依据是线程隔离性:线程私有(随线程创建而创建、线程销毁而销毁):1.程序计数器:当前线程执行的字节码行号指示器,是唯一一个无OOM的内存区域;2.虚拟机栈:存储栈帧,包含局部变量表、操作数栈、动态链接、方法出口,方法调用和执行都基于栈帧完成;3.本地方法栈:作用和虚拟机栈类似,专门为JNI本地方法(native方法)服务。线程共享(全局唯一,所有线程共享):1.堆:唯一存放对象实例和数组的区域,也是垃圾回收的核心区域;2.方法区:存储类信息、常量、静态变量、即时编译后的代码缓存等。2、程序计数器为什么不会发生内存溢出?程序计数器存储的仅仅是当前线程执行的字节码行号,数据量极小,内存占用固定且极低。同时JVM规范明确规定该区域不允许内存溢出,生命周期和线程绑定,线程结束内存立即释放,不存在持续占用内存的情况,所以永远不会出现OOM。3、虚拟机栈的栈帧包含哪些内容?栈溢出的原因是什么?一个方法的执行就对应一个栈帧,栈帧核心包含四部分:1.局部变量表:存放方法局部变量、基本数据类型、对象引用地址;2.操作数栈:执行字节码运算时,临时存放操作数的栈结构;3.动态链接:将符号引用转换为直接引用,完成方法、变量的绑定;4.方法返回地址:方法执行结束后,回到上层调用方法的指令地址。栈溢出(StackOverflowError)核心原因:1.方法递归调用过深,无限递归是最常见场景;2.单次方法调用层级过多,超出JVM虚拟机栈默认栈深限制。4、堆内存的结构划分?新生代和老年代的作用?以主流的G1、CMS、ParallelGC为例,堆内存主要分为新生代和老年代,默认新生代占堆内存1/3,老年代占2/3。1.新生代:分为Eden区、FromSurvivor、ToSurvivor,比例默认8:1:1。专门存放短期存活、临时创建的对象,绝大多数对象都是朝生夕灭,垃圾回收频率高、速度快。2.老年代:存放长期存活的对象、大对象。新生代对象经过多次GC存活后会晋升到老年代,大对象直接分配到老年代,老年代GC频率低、速度慢。5、方法区和元空间的区别?为什么要用元空间替换永久代?JDK1.8之前使用永久代实现方法区,JDK1.8及之后彻底移除永久代,使用元空间实现方法区逻辑。核心区别:1.永久代:使用JVM堆内存,受JVM固定堆大小限制,容易出现永久代OOM;2.元空间:使用本地操作系统内存,不受JVM堆限制,默认无固定上限,仅受系统剩余内存约束。替换原因:1.永久代内存固定,很难精准配置大小,过小容易OOM,过大浪费内存;2.元空间使用本地内存,动态扩容,大幅降低类加载过多导致的内存溢出问题;3.简化JVM内存结构,优化类加载、热部署的性能。三、类加载机制1、类的完整加载过程分为哪几步?类加载全过程分为加载、链接、初始化三大阶段,细分五步:1.加载:通过类全限定名读取class字节码文件,将字节码载入内存,生成运行时数据区的Class对象;2.验证:校验字节码合法性、安全性,避免恶意、错误字节码破坏JVM;3.准备:为类静态变量分配内存,赋默认初始值(int=0、boolean=false等,不赋值自定义初始值);4.解析:将代码中的符号引用替换为内存地址的直接引用;5.初始化:执行静态代码块、静态变量自定义赋值,是类加载的最后一步,也是主动加载的触发终点。2、什么是双亲委派模型?工作流程是什么?双亲委派模型是JVM默认的类加载机制,核心原则是向上委托、向下加载。JVM内置三层类加载器,优先级从上到下:启动类加载器>扩展类加载器>应用程序类加载器。工作流程:1.应用程序类加载器收到类加载请求,不会直接加载,向上委托给扩展类加载器;2.扩展类加载器继续向上委托给启动类加载器;3.启动类加载器是顶层加载器,无法继续向上委托,尝试加载该类;4.加载成功直接返回,加载失败则向下交由扩展类加载器加载;5.扩展类加载器加载失败,再向下交由应用程序类加载器完成加载。3、双亲委派模型的好处是什么?1.保证类的安全性:核心类(如String、Object)由顶层启动类加载器加载,避免开发者自定义同名核心类,防止篡改核心底层类;2.保证类的唯一性:同一个类只会被顶层加载器加载一次,避免重复加载导致类冲突、内存冗余;3.统一加载规范:规范类加载优先级,避免不同加载器重复加载,提升JVM稳定性。4、什么时候会打破双亲委派模型?常见场景有哪些?双亲委派是默认机制,并非强制机制,很多场景需要打破该模型,核心是子类加载器优先加载。常见场景:1.JDK中的SPI机制(JDBC、日志框架):核心接口由启动类加载器加载,实现类由应用类加载器加载,需要反向委派;2.热部署、热加载框架:需要自定义类加载器,优先加载本地修改后的类,覆盖旧类;3.中间件、容器(Tomcat、SpringBoot):需要隔离不同项目的类,避免包冲突,自定义类加载器打破双亲委派。四、垃圾回收GC核心知识点1、JVM哪些内存区域会发生GC?主要是堆内存和元空间,其中堆是GC的核心区域。线程私有区域(虚拟机栈、本地方法栈、程序计数器)随线程销毁自动释放内存,不需要垃圾回收。2、如何判断对象是垃圾对象?(存活判定)主流采用可达性分析算法,也是现代JVM唯一使用的算法。核心逻辑:以GCRoots作为起始节点,遍历内存引用链,能遍历到的对象就是存活对象,没有任何引用链相连的对象就是垃圾对象,可被回收。常见GCRoots:1.虚拟机栈中局部变量引用的对象;2.本地方法栈JNI引用的对象;3.方法区中静态变量、常量引用的对象;4.活跃线程持有的对象。注:传统的引用计数算法存在循环引用漏洞,JVM已废弃不用。3、Java中的引用类型有哪些?区别是什么?共四种引用,从强到弱排序:强引用、软引用、弱引用、虚引用。1.强引用:默认引用方式,只要有强引用,对象永远不会被回收,是最常用的引用;2.软引用:内存充足时不回收,内存不足触发OOM前一定会回收,适合做缓存(图片缓存、临时数据缓存);3.弱引用:只要发生GC,无论内存是否充足,都会被回收,适合存储非必须数据,典型场景ThreadLocal;4.虚引用:最弱的引用,无实际引用作用,仅用于跟踪对象回收状态,回收时收到系统通知,多用于堆外内存回收、监控。4、GC的分类:MinorGC、MajorGC、FullGC区别?1.MinorGC(新生代GC):只回收新生代,频率高、速度快、停顿时间短,几乎不会触发STW长时间卡顿,绝大多数GC都是MinorGC;2.MajorGC(老年代GC):只回收老年代,频率低、速度慢、停顿时间长,通常伴随MinorGC;3.FullGC(全堆GC):回收整个堆内存(新生代+老年代+元空间),开销最大、停顿最长,会严重影响系统性能,生产环境要尽量避免。触发FullGC的常见场景:老年代空间不足、元空间溢出、显式调用System.gc()、MinorGC后大量对象晋升老年代失败。5、常见的垃圾回收算法有哪些?各自特点?1.标记-清除算法:先标记垃圾对象,再统一清除。优点是简单,缺点是产生大量内存碎片,内存利用率低;2.复制算法:将存活对象复制到空白内存区域,清空原区域。无内存碎片、效率高,缺点是需要预留冗余内存,牺牲空间换时间,新生代主流使用该算法;3.标记-整理算法:标记垃圾后,将存活对象向内存一端整理压缩,清空末端垃圾。无内存碎片,无需冗余空间,缺点是移动对象开销大,老年代主流使用该算法。6、主流垃圾收集器对比?生产环境如何选择?1.Serial收集器:单线程收集器,GC时暂停所有用户线程,效率低,仅适用于客户端、小型程序;2.Parallel收集器:多线程并行收集器,注重吞吐量,牺牲停顿时间换取高吞吐量,是JDK8默认收集器,适合后台批量任务、对延迟不敏感的服务;3.CMS收集器:并发低延迟收集器,注重停顿时间,GC大部分阶段和用户线程并发执行,延迟低,缺点是内存碎片多、CPU占用高,适合互联网高并发低延迟服务,JDK14已废弃;4.G1收集器:分区式收集器,将堆划分为多个大小相等的Region,可精准控制停顿时间,兼顾吞吐量和低延迟,JDK9默认收集器,适合大内存、高并发服务;5.ZGC/Shenandoah:超低延迟收集器,停顿时间毫秒级,适合超大内存、极致低延迟的核心服务,JDK11+支持。五、JVM调优与内存溢出问题1、常见的OOM类型及产生原因?1.Javaheapspace(堆内存溢出):最常见,对象创建过多、过大,内存泄漏,堆内存配置过小,无法容纳存活对象;2.Metaspace(元空间溢出):动态生成类过多、热部署频繁、大量反射、动态代理,导致元空间存储的类信息超出上限;3.StackOverflowError(栈溢出):无限递归、方法调用层级过深;4.Directbuffermemory(堆外内存溢出):NIO堆外内存分配过多,未主动释放,超出最大堆外内存限制。2、内存泄漏和内存溢出的区别?1.内存泄漏:程序中无用对象持续持有引用,GC无法回收,内存被无效占用,不会立即报错,但会持续堆积内存;2.内存溢出:内存已经被占满,无法分配新内存,程序直接抛出OOM异常,服务报错。核心关系:长期内存泄漏一定会导致内存溢出,是量变到质变的过程。常见内存泄漏场景:静态集合持有对象、ThreadLocal未remove、连接未关闭、匿名内部类持有外部引用。3、生产环境常用JVM调优参数有哪些?1.堆内存配置:-Xms初始堆内存、-Xmx最大堆内存,生产环境一般设置相等,避免堆扩容震荡;2.新生代配置:-Xmn设置新生代大小,-XX:SurvivorRatio设置新生代分区比例;3.元空间配置:-XX:MetaspaceSize、-XX:MaxMetaspaceSize,防止元空间溢出;4.垃圾收集器指定:-XX:+UseG1GC、-XX:+UseCMS、-XX:+UseZGC;5.日志排查参数:-XX:+PrintGCDetails打印GC详细日志,-XX:+HeapDumpOnOutOfMemoryError发生OOM自动导出堆快照。4、线上JVM故障排查常用命令和工具?常用命令:1.jps:查看所有Java进程PID;2.jstat:实时监控GC次数、内存占用、GC耗时;3.jmap:导出堆快照、查看堆内存对象分布;4.jstack:打印线程堆栈,排查死锁、线程阻塞、死循环;5.jhat:分析堆快照文件。可视化工具:JConsole、VisualVM、MAT(内存分析工具,主打OOM、内存泄漏分析)。六、进阶面试题1、什么是STW?哪些场景会触发STW?STW即Stop-The-World,是JVM为了保证GC准确性,暂停所有用户业务线程,只保留GC线程工作的机制。所有垃圾回收都会触发STW,只是停顿时间长短不同。常见触发场景:MinorGC、MajorGC、FullGC、类重定义、热部署等。调优的核心目标之一就是减少STW

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论