面试题006-Java-JVM(下)

面试题006-Java-JVM(下)

目录

  • 面试题006-Java-JVM(下)
    • 题目自测
    • 题目答案
      • 1. 为什么需要GC?
      • 2. 有哪些常见的GC?
      • 3. Minor GC 和 Full GC有什么区别?
      • 4. 如何判断一个对象是否死亡?
      • 5. 讲一下可达性分析算法的流程?
      • 6. 如何判断一个常量是废弃常量? 如何判断一个类是无用的类?
      • 7. 垃圾收集有哪些算法,各自的特点?
      • 8. 默认的垃圾回收器是哪一个?
      • 9. 说一下G1垃圾收集器的步骤,有什么缺点?
      • 10. 什么是类加载?何时类加载?类加载流程?
      • 11. 知道哪些类加载器?类加载器之间的关系?
    • 参考资料

题目自测

  • 1. 为什么需要GC?
  • 2. 有哪些常见的GC?
  • 3. Minor GC 和 Full GC有什么区别?
  • 4. 如何判断一个对象是否死亡?
  • 5. 讲一下可达性分析算法的流程?
  • 6. 如何判断一个常量是废弃常量? 如何判断一个类是无用的类?
  • 7. 垃圾收集有哪些算法,各自的特点?
  • 8. 默认的垃圾回收器是哪一个?
  • 9. 说一下G1垃圾收集器的步骤,有什么缺点?
  • 10. 什么是类加载?何时类加载?类加载流程?
  • 11. 知道哪些类加载器?类加载器之间的关系?

题目答案

1. 为什么需要GC?

答:垃圾收集器通过自动内存管理,解决了手动管理内存时常见的问题(如内存泄漏和野指针)等,通过自动回收不在使用的对象、整理内存碎片等,极大的提升了程序的稳定性和开发效率。使得程序员可以专注业务逻辑的处理,而不必担心复杂的内存管理等问题。需要GC的主要原因如下

  • 防止内存泄漏:内存泄漏是指程序在运行过程中,未正确释放不再使用的内存,导致系统内存逐渐减少,最终可能导致系统崩溃。
  • 提高开发效率:GC自动化了内存管理,使得程序员可以更加专注业务逻辑的实现,不需要担心复杂的内存管理逻辑,从而提高了代码的开发效率和可维护性。
  • 优化内存使用:GC会定期扫描堆内存,回收不再使用的对象所占的内存,释放系统资源,从而优化内存的使用。
  • 提高程序稳定性:通过自动回收不再使用的对象,GC可以有效地防止内存耗尽,从而提高程序的稳定性和可用性。

2. 有哪些常见的GC?

答:垃圾收集器是实现垃圾回收操作的具体机制。常见的垃圾收集器有:

  • Serial GC:
    • 单线程的垃圾收集器,工作时会暂停所有的应用线程。
    • 适用于单处理器机器或者小型应用程序,堆内存较小的情况下效果较好。
    • 启动参数:-XX:+UseSerialGC
  • Parallel GC:
    • 多线程的垃圾收集器,可以利用多核处理器进行并行垃圾收集,提高吞吐量。JDK8的默认收集器。
    • 适用于多处理器机器和对响应时间要求不高的应用,目标是最大化应用程序的吞吐量。
    • 启动参数:-XX:+UseParallelGC 或者 -XX:+UseParallelOldGC。
  • CMS GC:
    • 低停顿的垃圾收集器,使用并发标记-清除算法,尽量减少垃圾收集导致的应用停顿时间。
    • 用于对响应时间要求高的应用程序,特别是需要大堆内存且停顿时间敏感的服务,如Web服务器。
    • 启动参数:-XX:+UseConcMarkSweepGC。
  • G1 GC:
    • 向服务器应用的垃圾收集器,采用分区算法,将堆划分为多个独立区域,优先回收垃圾最多的区域,能够提供更可预测的停顿时间。JDK9之后的默认收集器。
    • 适用于大堆内存、高吞吐量和低停顿时间要求的应用,是CMS GC的替代者。
    • 启动参数:-XX:+UseG1GC
  • ZGC:
    • 可扩展的低停顿垃圾收集器,设计目标是在拥有非常大的堆(TB级别)时,仍然能保持极低的停顿时间(通常在几毫秒以内)。
    • 适用于需要处理非常大堆内存且对停顿时间要求极高的应用。
    • 启动参数:-XX:+UseZGC

3. Minor GC 和 Full GC有什么区别?

答:Minor GC 和 Full GC是两种不同的垃圾收集操作,他们主要的区别是执行范围和触发条件。

  • Minor GC:
    • 作用范围:Minor GC 主要在新生代进行垃圾回收,新生代包括Eden区和两个Survivor区。
    • 触发条件:当新生代Eden区空间满时,会触发Minor GC。Eden区中的对象会被回收或复制到Survivor区。
    • 系统影响:Minor GC执行速度快,停顿时间短,对系统影响小。
  • Full GC:
    • 作用范围:Full GC 会回收整个堆、包括新生代和老年代,以及方法区或者元空间。
    • 触发条件:老年代空间不足、调用System.gc()方法、永久代/元空间内存不足、特定的JVM行为或调优参数配置也可能触发Full GC。
    • 系统影响:因为要清理整个堆的内存,开销较大,停顿时间长,对系统影响较大,需要避免频繁的Full GC。

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

答:如果一个对象不被任何变量或对象引用,那么它就是无效对象,需要被垃圾回收器回收。主要依据两种方式:引用计数法和可达性分析算法。

  • 引用计数法:
    • 在对象头维护着一个counter计数器,对象被引用一次计数器就加1,引用失效计数器减1。当计数器为0时就认为该对象死亡了。
    • 这个方法实现简单,效率高。但无法解决循环引用问题,容易导致内存泄漏。
  • 可达性分析算法:
    • 这是Java中实际采用的方法判断对象是否可以被回收。它的基本思想是通过一系列称为"GC Roots"的对象作为根节点,向下搜索。节点走过的所有路径称为引用链,当一个对象到GC Roots没有任何引用链相连的话,则证明该对象不可活,需要被回收。

5. 讲一下可达性分析算法的流程?

答:可达性分析算法是现代JVM中用来判断对象是否存活的主要方法。该算法通过从一组被称为“GC Roots”的根对象出发,沿着这些对象引用链,找到所有可达对象。那些不可达的对象会被认为是垃圾,可以被回收。

  1. 确定 GC Roots:首先需要确定一系列称为“GC Rooos”的对象集合。这些对象包括
    • 虚拟机栈(栈帧中本地变量表)中引用的对象。
    • 本地方法栈(Native方法)中引用的对象。
    • 方法区中类静态属性引用的对象。
    • 方法区中常量引用的对象。
    • 被同步锁持有的对象。
  2. 从根节点开始搜索:从GC Roots开始,JVM会通过深度优先搜索(DFS)或广度优先搜索(BFS),搜索过程中能被根节点引用的对象被认为是可达的,不会被回收。
  3. 标记不可达对象:搜索结束后,没有被搜索到的对象,被认为是不可达的。对这些不可达的对象进行标记。
  4. 二次标记与清理:在此阶段,JVM会进行筛选,判断这个对象是否有必要执行finalize()方法。如果没必要那么对象就会被直接回收。如果有必要执行finalize(),那么对象会被放入一个F-Queue队列中,等待后续处理。finalize()方法执行后,JVM会进行第二次可达性分析,如果对象仍然不可达,那么它将被彻底回收。

6. 如何判断一个常量是废弃常量? 如何判断一个类是无用的类?

答:

  • 判断废弃常量:如果常量池中的常量没有被任何对象和变量引用,就会被判断为废弃常量。如一个字符串"abc"进入了常量池,系统中没有任何的String对象引用这个常量,也没有其他地方引用这个字面量,那么"abc"会被清除出常量池。
  • 判断无用类:判断无用类的条件比较严格,要满足下面三个条件才会被认为是无用类
    • 该类的所有对象都已经被清除,也就是堆中没有任何该对象的信息。
    • 加载该类的ClassLoader已经被回收。
    • 该类的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

7. 垃圾收集有哪些算法,各自的特点?

答:垃圾收集算法用于自动管理和回收不再使用的内存空间。常见的垃圾回收算法有:

  • 标记-清除算法:首先遍历标记出所有不需要回收的对象,然后遍历堆中的对象,将标记的对象清除。
    • 特点:优点是简单,能有效回收无用对象。缺点是标记和清除效率不高,标记清除后会产生大量不连续的内存碎片。
  • 复制算法:将内存分成两块相等的区域,每次只使用其中的一块。当这一块使用完后,将还存活的对象复制到另一块。然后再把使用的空间全部清除。
    • 特点:适合新生代,只复制存活对象,速度快,没有内存碎片。但缺点是内存利用率低,只有一半内存空间被使用。
  • 标记-整理算法:第一阶段与清除标记算法一样。然后再移动存活对象,按照内存地址依次排序,然后清理掉端边界以外的内存。
    • 特点:适合老年代,解决了内存碎片问题。但是因为需要整理对象,所以效率也不高。
  • 分代收集算法:根据对象存活周期的不同,将内存划分为几块。一般Java堆分为新生代和老年代。新生代使用复制算法,老年代使用标记-清除算法、标记-整理算法。

8. 默认的垃圾回收器是哪一个?

答:在Java 8中,默认的垃圾回收器是Parallel GC。Java 9及之后,默认的垃圾回收器说G1 GC。

  • Parallel GC:主要追求高吞吐量,适用于需要大量数据处理、批处理或后台任务的应用。它通过多线程并行处理垃圾回收,能够充分利用多核处理器的能力。
  • G1 GC:设计目的是减少垃圾回收停顿时间,使其更适合需要低停顿时间的应用程序,例如需要较好响应时间的交互式应用。
  • 查看默认的垃圾收集器:
    java -XX:+PrintCommandLineFlags -version
    

9. 说一下G1垃圾收集器的步骤,有什么缺点?

答:G1 是一款面向服务端应用的垃圾收集器,将内存区域分成多个独立的Region。首先估计每个Region中垃圾的数量,每次从垃圾回收价值最大的Region开始回收,因此可以获得最大的回收效率。

G1 GC的步骤如下:

  • 初始标记:需要暂停应用线程,然后使用一条线程标记GC Roots直接可达的对象。
  • 并发标记:使用一条标记线程和用户线程一起并发执行。在此过程进行可达性分析。
  • 最终标记:暂停应用线程,使用多条标记线程,标记在并发标记阶段发生变动的对象。
  • 筛选回收:计算每个区域垃圾比例,选择回收价值大的区域,将存活对象复制到新区域,并整理旧区域。

G1收集器的缺点:

  • 调优复杂:G1 GC具有许多参数,调优过程复杂,可能需要大量的实验和监控。
  • 额外的内存开销:G1需要维护额外的数据结构来跟踪每个区域的状态,这会增加一定的内存开销。
  • 处理大对象性能较差:大对象会占用多个连续的区域,如果内存中没有足够连续的空闲区域,就可能导致GC频繁发生。

10. 什么是类加载?何时类加载?类加载流程?

答:类加载是JVM将字节码文件(.class)加载的内存中,并对其进行校验、解析、初始化,最终生成Class对象的过程。
类加载遵循“按需加载”的原则,即类在被首次主动使用时,JVM才会加载它。

  • 在遇到 new、putstatic、getstatic、invokestatic 字节码指令时,如果类尚未初始化,则需要先触发其初始化。
  • 对类进行反射调用时,如果类还没有初始化,则需要先触发其初始化。
  • 初始化一个类时,如果其父类还没有初始化,则需要先初始化父类。
  • 虚拟机启动时,需要指定一个包含 main() 方法的主类,虚拟机会先初始化这个主类。
  • 当使用 JDK 1.7 的动态语言支持时,如果一个 java.lang.invoke.MethodHandle 实例最后的解析结果为 REF_getStatic、REF_putStatic、REF_invokeStatic 的方法句柄,并且这个方法句柄所对应的类还没初始化,则需要先触发其初始化。

类加载的流程分为5个阶段,分别为加载、验证、准备、解析和初始化。

  • 加载:查找并加载类的二进制数据,创建一个代表该类的Class对象。
  • 验证:确保类文件的字节码符合JVM规范,没有安全性和稳定性问题。
  • 准备:为静态成员变量分配内存,并将其默认为初始化值。
  • 解析:将类中的符号引用转换为直接引用。
  • 初始化:执行类的静态初始化块和静态变量的初始化代码。

11. 知道哪些类加载器?类加载器之间的关系?

答:类加载器是负责加载类文件的对象,类加载器将字节码文件读取进内存,并将其转换为Class对象。Java中的类加载器体系具有层次结构,各种类加载器之间存在父子关系,遵循双亲委派模型。

  • 启动类加载器(Bootstrap ClassLoader):最顶层的加载类,由C/C++实现,通常表示为 null,并且没有父级,主要用来加载 JDK 内部的核心类库。
  • 扩展类加载器(Extension ClassLoader):主要负责加载 %JRE_HOME%/lib/ext 目录下的 jar 包和类以及被 java.ext.dirs 系统变量所指定的路径下的所有类
  • 应用程序类加载器(Application ClassLoader):面向我们用户的加载器,负责加载当前应用 classpath 下的所有 jar 包和类。
  • 自定义加载器(Custom ClassLoader):由用户自定义,适用于特殊需求,如加载加密的类文件、从网络加载类等。

类加载器之间的关系:

  • 每个类加载器都有一个父类加载器,除了启动类加载器。
  • 都遵循双亲委派模型。

参考资料

  • JavaGuide
  • 牛客网-Java面试宝典
  • Java虚拟机底层原理总结
  • ChatGPT

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/777446.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++之static关键字

文章目录 前提正文多重定义extern关键字使用staticstatic 全局变量(在.cpp文件中定义)static变量存放在哪里static变量可不可以放在.h文件中 static 函数static局部变量static 成员变量static 成员函数 总结参考链接 前提 好吧,八股,我又回来了。这次想…

8.14 矢量图层面要素2.5D渲染

文章目录 前言2.5D渲染QGis设置面符号为2.5D二次开发代码实现2.5D 总结 前言 本章介绍矢量图层面要素2.5D渲染的使用说明:文章中的示例代码均来自开源项目qgis_cpp_api_apps 2.5D渲染 2.5D渲染可以将多边形渲染为类3D效果。 QGis设置面符号为2.5D 以"hou…

数据库7.4

第二次作业 1.登陆数据库 2.创建数据库zoo 3.修改数据库zoo字符集为gbk 4.选择当前数据库为zoo 5.查看创建数据库zoo信息 6.删除数据库zoo C:\Windows\System32>mysql -uroot -p20040830Nmx mysql> create database zoo; alter database zoo character set gbk; mys…

Java springboot校园管理系统源码

Java springboot校园管理系统源码-014 下载地址:https://download.csdn.net/download/xiaohua1992/89364089 技术栈 运行环境:jdk8 tomcat9 mysql5.7 windows10 服务端技术:Spring Boot Mybatis VUE 使用说明 1.使用Navicati或者其它工…

VBA初学:零件成本统计之三(获取材料外协的金额)

第三步,从K3的数据库中获取金额 我这里是使用循环,通过任务单号将金额汇总出来,如果使用数组的话,还要按任务单写GROUP,还要去对应,不如循环直接一点 获取材料和外协金额的表格Sub getje()Dim rowcount A…

【JAVA入门】Day13 - 代码块

【JAVA入门】Day13 - 代码块 文章目录 【JAVA入门】Day13 - 代码块一、局部代码块二、构造代码块三、静态代码块 在 Java 中,两个大括号 { } 中间的部分叫一个代码块,代码块又分为:局部代码块、构造代码块、静态代码块三种。 一、局部代码块…

Linux应用---信号

写在前面:在前面的学习过程中,我们学习了进程间通信的管道以及内存映射的方式。这次我们介绍另外一种应用较为广泛的进程间通信的方式——信号。信号的内容比较多,是学习的重点,大家一定要认真学,多多思考。 一、信号概…

ASP.NET Core----基础学习01----HelloWorld---创建Blank空项目

文章目录 1. 创建新项目--方式一: blank2. 程序各文件介绍(Project name :ASP.Net_Blank)(1)launchSettings.json 启动方式的配置文件(2)appsettings.json 基础配置file参数的读取&a…

Vue 前端修改页面标题无需重新打包即可生效

在public文件夹下创建config.js文件 index.html页面修改 其他页面的标题都可以用window.title来引用就可以了!

【算法】(C语言):冒泡排序、选择排序、插入排序

冒泡排序 从第一个数据开始到第n-1个数据,依次和后面一个数据两两比较,数值小的在前。最终,最后一个数据(第n个数据)为最大值。从第一个数据开始到第n-2个数据,依次和后面一个数据两两比较,数值…

商务办公优选!AOC Q27E3S2商用显示器,打造卓越新体验!

摘要:助办公室一族纵横职场,实现高效舒适办公! 在日常商务办公中,对于办公室一族来说总有太多“难难难难难点”:工作任务繁琐,熬夜加班心力交瘁、长时间伏案工作导致颈椎、眼睛等出现问题,职业…

【吊打面试官系列-MyBatis面试题】为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?

大家好,我是锋哥。今天分享关于 【为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?】面试题,希望对大家有帮助; 为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里&#xf…

[从0开始轨迹预测][NMS]:NMS的应用(目标检测、轨迹预测)

非极大值抑制(Non-Maximum Suppression,简称NMS)是一种在计算机视觉中广泛应用的算法,主要用于消除冗余和重叠的边界框。在目标检测任务中,尤其是在使用诸如R-CNN系列的算法时,会产生大量的候选区域&#x…

Redis基础教程(九):redis有序集合

💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 💝&#x1f49…

华为仓颉可以取代 Java 吗?

大家好,我是君哥。 在最近的华为开发者大会上,华为亮相了仓颉编程语言,这是华为历经 5 年,投入大量研发成本沉淀的一门编程语言。 1 仓颉简介 按照官方报告,仓颉编程语言是一款面向全场景智能的新一代编程语言&#…

使用JAR命令打包JAR文件使用Maven打包使用Gradle打包打包Spring Boot应用

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

XLSX + LuckySheet + LuckyExcel + Web Worker实现前端的excel预览

文章目录 功能简介简单代码实现web worker 版本效果参考 功能简介 通过LuckyExcel的transformExcelToLucky方法, 我们可以把一个文件直接转成LuckySheet需要的json字符串, 之后我们就可以用LuckySheet预览excelLuckyExcel只能解析xlsx格式的excel文件&a…

机器学习——随机森林

随机森林 1、集成学习方法 通过构造多个模型组合来解决单一的问题。它的原理是生成多个分类器/模型,各自独立的学习和做出预测。这些预测最后会结合成组合预测,因此优于任何一个单分类得到的预测。 2、什么是随机森林? 随机森林是一个包含…

Midjourney 预设

使用命令/settings 进入预设,根据点击不同选项来配置。 🌹 1. 设置工作所使用的模型版本。 1️⃣ MJ Version 1 2️⃣ MJ Version 2 3️⃣ MJ Version 3 4️⃣ MJ Version 4 5️⃣ MJ Version 5 5️⃣ MJ Version 5.1 🔧Raw Mode 🌈 Niji Version 4 🍎 Niji Versio…

【pytorch16】MLP反向传播

链式法则回顾 多输出感知机的推导公式回顾 只与w相关的输出节点和输入节点有关 多层多输入感知机 扩展为多层感知机的话,意味着还有一些层(理解为隐藏层σ函数),暂且设置为 x j x_{j} xj​层 对于 x j x_{j} xj​层如果把前面的…