面试题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.mzph.cn/pingmian/41775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS修复OpenSSH漏洞升级到openssh 9.7 RPM更新包

在做政府和学校单位网站时,经常需要服务器扫描检测,经常被OpenSSH Server远程代码执行漏洞(CVE-2024-6387)安全风险通告,出了报告需要升级OpenSSH。 使用yum update openssh是无法更新到最新的,因为系统里的…

VS code修改底部的行号的状态栏颜色

VSCode截图 相信很多小伙伴被底部的蓝色状态栏困扰很久了 处理的方式有两种: 1、隐藏状态栏 2、修改其背景颜色 第一种方法大伙都会,今天就使用第二种方法。 1、点击齿轮进入setting 2、我现在用的新版本,设置不是以前那种json格式展示&…

17-JS封装:工具类方法

目录 一、extend方法 二、添加一些工具类方法:$.xxx() 实现1: 实现2: 一、extend方法 jQuery.fn.extend jQuery.extend function(...args){let target,source[];source[...args];//判断2种情况 //$.extend({}) -->给$添加属性//$.…

计算机提示由于找不到concrt140.dll怎么办,7种解决方法可以对比

在电脑中打开游戏或许软件出现找不到concrt140.dll无法继续执行代码怎么办?concrt140.dll是什么?丢失要怎么解决?下面给大家分析一下concrt140.dll文件是什么与concrt140.dll丢失的多种解决方法!相信对你有帮助! 一、c…

hdu物联网硬件实验2 GPIO亮灯

学院 班级 学号 姓名 日期 成绩 实验题目 GPIO亮灯 实验目的 点亮三个灯闪烁频率为一秒 硬件原理 无 关键代码及注释 const int ledPin1 GREEN_LED; // the number of the LED pin const int ledPin2 YELLOW_LED; const int ledPin3 RED…

Spring Boot与Spring Cloud Config的集成

Spring Boot与Spring Cloud Config的集成 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 一、Spring Cloud Config简介与背景 在微服务架构中,配…

FPGA开发笔试1

1. 流程简介 我是两天前有FPGA公司的HR来问我实习的事情,她当时问我距离能不能接受,不过确实距离有点远(地铁通勤要将近一个半小时),然后她说给我约个时间,抽空做1个小时的题目(线上做&#xf…

2024年【金属非金属矿山(地下矿山)安全管理人员】考试报名及金属非金属矿山(地下矿山)安全管理人员模拟考试题

题库来源:安全生产模拟考试一点通公众号小程序 2024年金属非金属矿山(地下矿山)安全管理人员考试报名为正在备考金属非金属矿山(地下矿山)安全管理人员操作证的学员准备的理论考试专题,每个月更新的金属非…

CTF常用sql注入(三)无列名注入

0x06 无列名 适用于无法正确的查出结果,比如把information_schema给过滤了 join 联合 select * from users;select 1,2,3 union select * from users;列名被替换成了1,2,3, 我们再利用子查询和别名查 select 2 from (select 1,2,3 union select * f…

Go语言--工程管理、临时/永久设置GOPATH、main函数以及init函数

工作区 Go 代码必须放在工作区中。工作区其实就是一个对应于特定工程的目录,它应包含3个子目录:src 目录、pkg目录和bin 目录。 src 目录:用于以代码包的形式组织并保存 Go源码文件。(比如:.go.chs等)pkg 目录:用于存放经由 go install 命令构建安装后的代码包(包…

芯片基识 | 掰开揉碎讲 FIFO(同步FIFO和异步FIFO)

文章目录 一、什么是FIFO二、为什么要用FIFO三、什么时候用FIFO四、FIFO分类五、同步FIFO1. 同步FIFO电路框图2. 同步FIFO空满判断3. 同步FIFO设计代码4. 同步FIFO仿真结果 六、异步FIFO1、异步FIFO的电路框图2 、亚稳态3、打两拍4、格雷码5、如何判断异步FIFO的空满&#xff0…

react v18 less使用(craco)

方案一、弹出配置(不推荐) 安装依赖:yarn add less less-loader 首先 执行 yarn eject 弹出配置项文件(注意:弹出配置不可逆!) 在 config 文件夹中 找到 webpack.config.js,在如图…

Spring Boot自动配置详解

Spring Boot自动配置详解 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们来详细探讨Spring Boot的自动配置机制。Spring Boot自动配置是其核心特性之一…

爆破片和安全阀

一、爆破片介绍 爆破片是一种用于安全释放压力的结构,通常应用于压力容器、管道和设备中,以防止由于压力过高而导致的灾难性故障。在压力超过设定值时,爆破片会破裂,从而迅速将过压泄放,保护设备和人员安全 爆破片通常…

Java并发编程详解

在现代软件开发中,多线程和并发编程是提高应用程序性能的关键技术之一。Java提供了丰富的并发编程工具,使得开发者能够高效地实现多线程应用。本文将详细介绍Java中的线程和并发工具,探讨线程安全的概念,并分享实现线程安全的方法…

java Web 优秀本科毕业论文系统用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 优秀本科毕业论文系统是一套完善的web设计系统,对理解JSP java serlvet 编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发,数据库为Mysql5.0&a…

Selenium的这些自动化测试技巧你知道几个?

Selenium自动化测试技巧 与以前瀑布式开发模式不同,现在软件测试人员具有使用自动化工具执行测试用例套件的优势,而以前,测试人员习惯于通过测试脚本执行来完成测试。 但自动化测试的目的不是完全摆脱手动测试,而是最大程度地减少…

数据库——常用SQL语句

title: 数据库——常用SQL语句 date: 2024-07-06 12:25:36 tags: 数据库 categories: 数据库 cover: /image/T1.jpg description: 数据库的常用SQL语句 SQL语句 SQL(Structured Query Language)是一种用于访问和操作数据库系统的标准编程语言。它允许用…

用WPF实现的窗体是怎么运行的?

在WPF应用程序中,窗体的启动通常是由Application类的实例来管理的。以下是WPF应用程序启动的基本流程: 初始化Application实例: 当WPF应用程序开始运行时,会自动创建一个Application实例。这个实例负责整个应用的生命周期管理&…

24.【C语言】getchar putchar的使用

1.基本作用 用户输入字符,getchar()获取字符(含\n:即键入的Enter)(字符本质上是以ASCII值或EOF(-1)存储的)(与scanf有区别) putchar() 打印字符(把得到的A…