JVM基础面试题库

1.JVM中的垃圾收集器有哪些,它们的工作原理是什么?

JVM中的垃圾收集器主要包括以下几种:

1、 Serial收集器:它是一个单线程收集器,工作时会暂停所有其他工作线程("Stop-The-World"),它的优点是简单高效(与其他收集器的单线程比),适用于单核处理器的环境。

2、 ParNew收集器:可以看作是Serial收集器的多线程版本,主要用于新生代的垃圾收集,适合多核处理器环境。

3、 Parallel Scavenge收集器:也是一个新生代垃圾收集器,使用多线程收集,注重吞吐量(CPU用于运行用户代码的时间比率)。

4、 Serial Old收集器:是Serial收集器的老年代版本,单线程,采用标记-整理算法。

5、 Parallel Old收集器:是Parallel Scavenge收集器的老年代版本,使用多线程并行收集,目标是提高系统吞吐量。

6、 CMS(Concurrent Mark Sweep)收集器:以获取最短回收停顿时间为目标,使用多线程并发标记和清除算法。

7、 G1(Garbage-First)收集器:采用分区堆(Heap)和增量式垃圾回收,目标是兼顾吞吐量和停顿时间。

2.JVM中的类加载器有哪些,它们各自的作用是什么?

JVM中的类加载器主要有三种:

1、启动类加载器(BootstrapClassLoader) :它负责加载存放在<JAVA_HOME>/jre/lib目录中,或者被-Xbootclasspath参数指定的路径中的类库。

2、扩展类加载器(Extension ClassLoader) :它负责加载<JAVA_HOME>/jre/lib/ext目录中的类库。

3、应用程序类加载器(Application ClassLoader) :它负责加载用户类路径(Classpath)上所指定的类库。

每个类加载器都有其特定的加载范围,这种层次关系保证了Java程序稳定运行。

3.JVM中垃圾回收的算法有哪些?

JVM垃圾回收的主要算法包括:

1、标记-清除算法(Mark-Sweep) :先标记出所有需要回收的对象,然后统一清除这些对象。

2、复制算法(Copying) :将内存分为两块,每次只使用其中一块,当这一块的内存用完了,就把还活着的对象复制到另一块上去。

3、标记-整理算法(Mark-Compact) :类似于标记-清除算法,但在清除后会进行内存整理,减少碎片。

4、分代收集算法(Generational Collection) :根据对象存活周期的不同将内存划分为几块,如年轻代、老年代等,采用适合各个年代的收集算法。

4.JVM如何判断对象是否死亡?

JVM判断对象是否死亡主要有两种方式:

1、引用计数法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。

2、可达性分析:通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

5.JVM中有哪些引用类型?

JVM中主要有四种引用类型:

1、强引用(Strong Reference) :普通的对象引用,只要强引用还存在,垃圾回收器永远不会回收掉被引用的对象。

2、软引用(Soft Reference) :内存不足时,会被垃圾回收器回收掉。

3、弱引用(Weak Reference) :只能生存到下一次垃圾收集之前,当垃圾回收器工作时,无论内存是否足够,都会回收掉只被弱引用关联的对象。

4、虚引用(Phantom Reference) :最弱的一种引用关系,无法通过虚引用来获取对象实例,它的存在仅仅是为了在这个对象被收集器回收时收到一个系统通知。

6.JVM的永久代(PermGen)和元空间(Metaspace)有什么区别?

永久代(PermGen)和元空间(Metaspace)是JVM中存储类元数据的区域,二者的主要区别如下:

1、存储位置:永久代是在JVM的堆内存中,而元空间位于本地内存。

2、大小限制:永久代的大小是固定的,容易出现内存溢出;元空间利用本地内存,所以默认情况下只受本地内存大小限制。

3、回收机制:永久代的回收主要针对常量池的回收和对类型的卸载;元空间提供了更好的性能,在使用本地内存的同时,减少了垃圾收集的频率。

7.JVM中的堆和栈有什么区别?

堆和栈是JVM中两个重要的内存区域,它们的主要区别如下:

1、用途:堆用于存储对象实例和数组,是垃圾回收的主要区域;栈用于存储局部变量、操作数栈和控制流。

2、线程共享性:堆是被所有线程共享的内存区域,而栈是线程私有的。

3、内存分配:堆的内存分配是动态的,适用于动态对象的存储;栈的内存分配是连续的,适用于临时变量的存储。

4、内存回收:堆的内存回收由垃圾回收器处理,栈的内存分配和回收是自动的。

8.JVM中Full GC触发的原因有哪些?

Full GC触发的原因主要有以下几点:

1、老年代空间不足:老年代存放长期存活的对象,当老年代空间不足时,会触发Full GC。

2、永久代或元空间不足:当存储类元数据的区域空间不足时,同样会触发Full GC。

3、System.gc()调用:系统调用System.gc()时,通常会触发Full GC。

4、JVM参数:由于某些JVM参数设置不当,如过小的堆空间,也可能触发Full GC。

5、Eden区、Survivor区向老年代晋升失败:如果Eden区或Survivor区中的对象在Minor GC后仍然存活,并且老年代无法容纳这些对象,也会触发Full GC。

9.JVM中的类加载器有哪些,它们各自的作用是什么?

JVM中的类加载器主要有以下几种:

1、启动类加载器(Bootstrap ClassLoader): 加载Java的核心库(JAVA_HOME/jre/lib/rt.jar等),是所有类加载器的父加载器。

2、扩展类加载器(Extension ClassLoader): 加载JAVA_HOME/jre/lib/ext目录中或者由java.ext.dirs系统属性指定的路径中的类库。

3、应用程序类加载器(Application ClassLoader): 加载用户类路径(Classpath)上的类库,如果应用中没有定义自己的类加载器,这将是默认的类加载器。

每个类加载器都有自己的职责范围,确保Java应用能够加载类的灵活性和安全性。

10.JVM内存区域划分及其作用是什么?

JVM的内存区域主要包括:

1、方法区(Method Area): 存储类信息、常量、静态变量等。

2、堆(Heap): 存放对象实例,是垃圾收集器管理的主要区域。

3、栈(Stack): 存放方法的局部变量表、操作数栈、动态链接等信息。

4、程序计数器(Program Counter Register): 当前线程所执行的字节码的行号指示器。

5、本地方法栈(Native Method Stack): 为Native方法服务。

这些区域各司其职,共同支持了Java程序的运行。

11.JVM中垃圾收集的算法有哪些?

JVM垃圾收集的主要算法包括:

1、标记-清除算法(Mark-Sweep): 标记出所有需要回收的对象,然后统一回收这些对象。

2、复制算法(Copying): 将内存分为两块,每次只使用其中一块,垃圾收集时将活动对象复制到另一块上。

3、标记-整理算法(Mark-Compact): 标记过程与标记-清除算法相同,但后续步骤是将所有存活的对象向一端移动,然后清理掉端边界以外的内存。

4、分代收集算法(Generational Collection): 根据对象存活周期的不同将内存划分为几块,比如年轻代、老年代等,各个年代使用不同的垃圾收集算法。

这些算法各有优劣,JVM根据具体情况选择合适的算法或算法组合进行垃圾回收。

12.JVM中的双亲委派模型。

JVM中的双亲委派模型是类加载器的一种工作机制,其主要特点如下:

1、工作流程: 当一个类加载器尝试加载某个类时,它首先不会尝试自己去加载这个类,而是把这个请求委托给父类加载器去完成,依次递归,如果父加载器无法完成这个加载(比如它的搜索范围中没有这个类),子加载器才会尝试自己去加载这个类。

2、优点: 这个模型可以避免类的重复加载,保护程序安全防止核心API被随意篡改。

3、破坏双亲委派: 在某些情况下,比如SPI(Service Provider Interface)服务,类加载器需要破坏双亲委派模型以便于服务提供者能够提供接口实现。

13.JVM中的永久代(PermGen)和元空间(Metaspace)有何区别?

永久代(PermGen)和元空间(Metaspace)是JVM内存的两个不同部分:

1、永久代(PermGen): 在JVM早期版本中,用于存储类的元数据、字符串常量等。它有固定的大小,容易发生OutOfMemoryError。

2、元空间(Metaspace): 在Java 8中,永久代被元空间所替代。元空间使用本地内存,存储类的元数据。相比永久代,它的大小受物理内存的限制,更加灵活。

3、性能优化: 元空间的引入减少了垃圾收集的频率,提升了性能,尤其是在加载大量类的应用中。

14.JVM优化的常见手段有哪些?

JVM优化通常涉及以下几个方面:

1、调整堆大小: 适当增加JVM堆的大小可以减少垃圾收集的频率,但过大的堆可能会增加垃圾收集的时间。

2、选择合适的垃圾收集器: 根据应用的特点选择最合适的垃圾收集器,如G1、CMS等。

3、线程堆栈大小(-Xss): 适当的线程堆栈大小可以减少内存的使用,但太小可能会导致栈溢出。

4、分析并优化代码: 优化应用代码,减少内存泄漏和不必要的对象创建。

5、JVM参数调优: 通过调整JVM启动参数,优化JVM的性能。

6、使用性能分析工具: 利用JProfiler、MAT、VisualVM等工具分析性能问题。

15.JVM中的Just-In-Time(JIT)编译器。

JVM中的Just-In-Time(JIT)编译器是一种提高程序运行效率的机制,其工作原理如下:

1、编译时机: JIT编译器在运行时将字节码转换为本地机器码,而非在程序运行之前。

2、优化代码: JIT编译器可以根据运行时的数据和行为对代码进行优化。

3、提升性能: JIT编译可以显著提高Java程序的性能,减少程序运行时间。

4、适应性: JIT编译器可以适应程序的运行特性,进行动态优化。

全部评论

相关推荐

12-08 12:43
已编辑
门头沟学院 Java
那些杀不死我的&nbsp;反复追着我杀!!1.jvm包含哪几部分classloader:将编译(.java-&gt;.class)好的java字节码文件(.class文件)&nbsp;加载到内存中(也就是运行时数据区Runtime&nbsp;data&nbsp;area&nbsp;存放运行时数据(线程私有:栈&nbsp;本地方法栈&nbsp;pc&nbsp;,进程级(也就是所有线程共享):堆&nbsp;本地方法区)Execution&nbsp;engine&nbsp;执行引擎,class文件被加载后&nbsp;将指令和数据放在内存中&nbsp;执行引擎负责将命令解释给os&nbsp;也就是将JVM指令翻译为os指令集Native&nbsp;interface:本地库接口2.jvm内存结构/运行时数据区线程私有的:栈(每个方法执行时创建栈帧&nbsp;存局部变量表等)&nbsp;本地方法栈(为Native方法提供服务)&nbsp;程序计数器(存当前线程执行的字节码指令地址)线程共享:堆(最大的内存区&nbsp;存对象实例、类对象)&nbsp;方法区&nbsp;(存类有关的信息&nbsp;静态变量等)3.说一下永久代和元空间都是对&nbsp;方法区&nbsp;的实现永久代:JDK7&nbsp;及之前的实现,属于堆内存的一部分,有固定大小限制(通过-XX:PermSize/-XX:MaxPermSize设置),存储类元信息、常量池等,易触发永久代&nbsp;OOM元空间:JDK8&nbsp;及之后的实现,使用本地内存(不在堆中),大小受物理内存限制(默认无上限),仅需通过-XX:MetaspaceSize设置初始触发&nbsp;GC&nbsp;的阈值4.为什么jdk8要将永久代替换为元空间解决永久代OOM问题&nbsp;简化类元数据管理&nbsp;兼容JVM规范5.类加载过程加载:通过类全限定名获取字节码流,将字节码转化为方法区的类元数据,同时在堆中生成Class对象验证:确保字节码符合&nbsp;JVM&nbsp;规范(如文件格式验证、语义验证),防止恶意字节码破坏&nbsp;JVM&nbsp;安全准备:为类的静态变量分配内存并赋默认值(如&nbsp;int&nbsp;赋&nbsp;0、对象赋&nbsp;null),不执行赋值语句(赋值在初始化阶段)解析:将常量池中的符号引用替换为直接引用(如类、方法的内存地址),该阶段可延迟到初始化后执行。初始化:执行&lt;clinit&gt;方法(静态变量赋值&nbsp;+&nbsp;静态代码块),触发时机是&nbsp;“主动使用”(new&nbsp;对象、访问静态成员、反射、初始化子类、主类),且每个类仅初始化一次6.类加载机制(双亲委派制)1类加载器收到加载请求&nbsp;&nbsp;-&gt;&nbsp;2将请求委托给父加载器,一直向上委托,直到启动类加载器&nbsp;-&gt;&nbsp;3启动加载器检查是否能加载这个类,能则使用当前加载器,否则向下传递&nbsp;-&gt;4重复步骤3&nbsp;如果找不到&nbsp;class&nbsp;not&nbsp;foundJVM&nbsp;默认类加载器层级:启动类加载器(Bootstrap)→扩展类加载器(Ext)→应用程序类加载器(App)→自定义类加载器7.why双亲委派保护核心类库(如String由启动类加载器加载,避免自定义类篡改替换)防止类重复加载8.自定义类加载器需要注意什么重写findClass方法(not&nbsp;loadClass,避免破坏双亲委派)9.双亲委派模型有哪些破坏场景&nbsp;为什么要破坏Tomcat的WebAppClassLoader:Tomcat&nbsp;为每个&nbsp;Web&nbsp;应用创建独立类加载器,优先加载应用内的类(而非委托父类),目的是隔离不同&nbsp;Web&nbsp;应用的类(防止不同应用的同包同类冲突)JDBC&nbsp;的&nbsp;SPI&nbsp;加载:JDBC&nbsp;的核心接口java.sql.Driver由启动类加载器加载,但具体实现(如&nbsp;MySQL&nbsp;驱动)在第三方包,启动类加载器无法加载,因此&nbsp;DriverManager&nbsp;通过线程上下文类加载器(破坏双亲委派)加载实现类(可能会让详细说一下SPI机制一些热部署实现:自定义类加载器加载更新后的类10.类卸载条件类所有实例被完全回收&nbsp;类加载器被完全回收&nbsp;Class对象无任何引用(FullGC时发生11.介绍一下gc机制涉及对象可回收判定、垃圾收集算法、分代收集模型、垃圾收集器、GC&nbsp;触发时机等维度(问这么大&nbsp;吟唱启动12.常见gc算法标记-清除,标记-复制,标记-整理,分代收集13.介绍一下CMS和G1(1)CMS&nbsp;收集器(老年代专用)核心流程:初始标记(STW,标记&nbsp;GC&nbsp;Roots&nbsp;直接关联对象)→并发标记(无&nbsp;STW,遍历引用链)→重新标记(STW,修正并发标记的遗漏)→并发清除(无&nbsp;STW,清理可回收对象)优点:并发收集,STW&nbsp;时间短,适合低延迟场景缺点:产生内存碎片、CPU&nbsp;消耗高(并发阶段占用&nbsp;CPU)、依赖老年代空间预留(易触发&nbsp;Full&nbsp;GC)(2)G1&nbsp;收集器(全堆收集)核心流程:将堆划分为多个大小相等的&nbsp;Region,包含新生代&nbsp;Region&nbsp;和老年代&nbsp;Region;流程为初始标记→并发标记→最终标记→筛选回收(STW,优先回收垃圾多的&nbsp;Region)优点:兼顾吞吐量和延迟、可预测&nbsp;STW&nbsp;时间(通过-XX:MaxGCPauseMillis设置)、无内存碎片(回收时整理&nbsp;Region)缺点:内存占用高(维护&nbsp;Remembered&nbsp;Set)、小内存场景下性能不如&nbsp;CMS14.jvm如何判断对象是可回收的早期方案引用计数法(无法解决循环引用问题)可达性分析算法判定对象是否不可达,结合引用类型细分可回收时机,finalize&nbsp;机制完成最终判定15.能否将对象分配在栈上jvm针对“逃逸”做了优化分析对象的作用域是否逃出方法&nbsp;/&nbsp;线程,若逃逸则可直接分配在栈上&nbsp;无需gc16.jvm调优核心思路是什么监控&nbsp;分析&nbsp;参数调整&nbsp;验证17.一般会调整哪些jvm参数堆大小:-Xms2g&nbsp;-Xmx2g(初始堆&nbsp;=&nbsp;最大堆,避免堆动态扩展的开销)新生代大小:-Xmn512m(新生代占堆的&nbsp;1/4~1/3,过小会导致对象提前进入老年代)Survivor&nbsp;比例:-XX:SurvivorRatio=8(Eden:S0:S1=8:1:1,保证新生代对象有足够空间存活)晋升老年代年龄:-XX:MaxTenuringThreshold&nbsp;-XX:InitialTenuringThresholdGC&nbsp;收集器:-XX:+UseG1GC(默认推荐,兼顾吞吐量和延迟)、-XX:+UseZGC(低延迟场景)GC&nbsp;日志:-XX:+PrintGCDetails&nbsp;-Xloggc:gc.log(输出&nbsp;GC&nbsp;日志用于分析)元空间:-XX:MetaspaceSize=128m&nbsp;-XX:MaxMetaspaceSize=256m(限制元空间大小,避免元空间&nbsp;OOM)18.Jvm调优经验《没有经验!!》(回去等通知吧19.内存泄漏和OOM的区别?如何排查(1)内存泄漏:对象已无业务意义,但仍被引用(如ThreadLocal......),导致无法被&nbsp;GC&nbsp;回收,长期积累会引发&nbsp;OOM①&nbsp;jmap&nbsp;-dump:format=b,file=heap.hprof导出堆快照;②&nbsp;MAT分析快照,定位&nbsp;“无法回收的大对象”&nbsp;和&nbsp;“持有其引用的&nbsp;GC&nbsp;Roots&nbsp;③结合&nbsp;Arthas&nbsp;的jvm/heapdump命令定位泄漏代码(如静态&nbsp;Map&nbsp;未清理)(2)OOM:JVM&nbsp;内存不足(如堆&nbsp;/&nbsp;元空间&nbsp;/&nbsp;栈超出上限),无法为新对象分配内存,直接抛出&nbsp;OOM&nbsp;异常①&nbsp;看&nbsp;OOM&nbsp;类型(堆&nbsp;OOM&nbsp;/&nbsp;元空间&nbsp;OOM&nbsp;/&nbsp;栈&nbsp;OOM)②&nbsp;堆&nbsp;OOM&nbsp;分析对象分布(是否大对象过多)&nbsp;元空间&nbsp;OOM&nbsp;检查类加载数量(是否频繁动态生成类)&nbsp;栈&nbsp;OOM&nbsp;检查递归深度或线程数20.线上OOM问题如何排查21.如何分析gc日志22.线上频繁FullGC如何排查23.讲一下对jvm的理解(太大了&nbsp;上文内容挑一些吟唱24.jmmJava&nbsp;Memory&nbsp;Model&nbsp;Java&nbsp;内存模型,Java&nbsp;虚拟机规范中定义的一种抽象内存模型,并非物理内存的实际布局,其核心目标是解决多线程环境下的原子性、可见性、有序性问题,为多线程编程提供内存访问的一致性规则欢迎佬赐教上辈子🔪👨放🔥&nbsp;这辈子十月(底)秋招!!
查看23道真题和解析
点赞 评论 收藏
分享
评论
2
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务