Java面试黄金宝典11

news2025/3/27 2:10:48

1. 什么是 JMM 内存模型

  • 定义

JMM(Java Memory Model)即 Java 内存模型,它并非真实的物理内存结构,而是一种抽象的概念。其主要作用是规范 Java 虚拟机与计算机主内存(Main Memory)之间的交互方式,目的是屏蔽不同硬件和操作系统在内存访问上的差异,确保 Java 程序在各种平台上都能获得一致的内存访问效果。

在 JMM 的体系中,线程之间的共享变量存于主内存之中。而每个线程都拥有自己的本地内存(Local Memory),这里的本地内存是一个抽象概念,它涵盖了缓存、写缓冲区、寄存器等区域。线程若要对共享变量进行操作,必须先将变量从主内存拷贝到本地内存,操作完成后再把结果刷新回主内存。

  • 原理

JMM 是基于缓存一致性协议构建的,它通过定义一系列规则来保障多线程环境下的内存可见性和有序性。举例来说,当一个线程对共享变量的值进行修改后,它需要把修改后的值刷新回主内存;而其他线程在读取该变量时,就需要从主内存中重新获取最新的值,以此来保证各个线程看到的共享变量值是一致的。

  • 要点
  1. 主内存:是所有线程共享的内存区域,用于存储共享变量。
  2. 本地内存:每个线程私有的内存区域,存储着该线程使用的共享变量的副本。
  3. 线程通信:线程之间的通信是通过主内存来完成的,线程不能直接访问其他线程的本地内存。

  • 应用

JMM 与硬件内存架构紧密相关,它在一定程度上模拟了硬件的内存访问模式。同时,JMM 为 Java 中的并发编程奠定了基础,像 volatilesynchronized 等关键字的语义都依赖于 JMM 来实现。例如,volatile 关键字通过保证变量的可见性,确保一个线程对 volatile 变量的修改能立即被其他线程看到,这背后就是 JMM 的规则在起作用。

2. JMM 中的 happens - before 原则

  • 定义

happens - before 原则是 JMM 中用于判断数据是否存在竞争、线程是否安全的重要规则。如果操作 A happens - before 操作 B,那么操作 A 的执行结果对操作 B 是可见的,并且操作 A 的执行顺序在操作 B 之前。不过需要注意的是,这里的 “顺序” 并非严格的时间先后顺序,而是强调操作结果的可见性。

  • 原理

happens - before 原则的核心在于保障多线程环境下的有序性和可见性。它并不要求前一个操作在时间上一定先于后一个操作执行,而是着重于前一个操作的结果对后一个操作是可见的。例如,在多线程环境中,可能会存在指令重排序的情况,但只要满足 happens - before 原则,就不会影响程序的正确性。

  • 要点
  1. 程序顺序规则:在一个线程内部,每个操作 happens - before 该线程中任意后续操作。这保证了单线程程序的执行顺序符合代码的编写顺序。
  2. 监视器锁规则:对一个锁的解锁操作 happens - before 随后对这个锁的加锁操作。这确保了在同一时刻只有一个线程能够访问被锁保护的代码块,并且线程在释放锁后,其他线程能够看到该线程对共享变量所做的修改。
  3. volatile 变量规则:对一个 volatile 域的写操作 happens - before 任意后续对这个 volatile 域的读操作。这保证了 volatile 变量的可见性,使得一个线程对 volatile 变量的修改能够立即被其他线程感知。
  4. 传递性:如果 A happens - before B,且 B happens - before C,那么 A happens - before C。通过传递性,可以将多个操作之间的 happens - before 关系进行扩展。

  • 应用

happens - before 原则是 JMM 的核心内容,它为 Java 程序员提供了一种简单的方式来推理多线程程序的正确性。在编写并发程序时,遵循 happens - before 原则可以有效避免数据竞争和内存可见性问题。例如,在使用线程池时,线程池的任务提交和任务执行之间就存在 happens - before 关系,开发者可以利用这一原则来确保任务执行的正确性。

3. 什么是堆中的永久代

  • 定义

在 Java 8 之前,Java 堆内存被划分为新生代、老年代和永久代。永久代主要用于存储类的元数据信息,如类的结构、方法、字段、常量池等。永久代虽然和堆内存一起进行管理,但它的垃圾回收机制与堆的其他部分有所不同。

  • 原理

永久代的设计初衷是为了存储类的元数据,因为这些数据在程序运行期间通常是固定不变的。JVM 在类加载时会将类的元数据信息存储在永久代中,直到类被卸载。由于类的元数据相对稳定,所以永久代的垃圾回收频率较低。

  • 要点
  1. 存储内容:永久代存储的是类的元数据,而不是对象实例。
  2. 大小限制:永久代有固定的大小限制,当存储的元数据超过这个限制时,就容易出现 OutOfMemoryError: PermGen space 错误。
  3. 版本变化:从 Java 8 开始,永久代被元空间(Metaspace)取代。

  • 应用

元空间与永久代的主要区别在于,元空间使用本地内存(Native Memory),而不是 JVM 堆内存。这使得元空间的大小不再受 JVM 堆大小的限制,减少了 OutOfMemoryError: PermGen space 错误的发生。例如,在一些大型的 Java 应用中,可能会加载大量的类,使用永久代时容易出现空间不足的问题,而使用元空间则可以更好地应对这种情况。

4. 什么样的对象需要回收

  • 定义

在 Java 中,当一个对象不再被任何引用指向时,该对象就成为了垃圾对象,需要被回收。判断一个对象是否为垃圾对象通常有两种方法:引用计数法和可达性分析法。

  • 原理
  1. 引用计数法:为每个对象维护一个引用计数器,当有一个新的引用指向该对象时,计数器加 1;当一个引用不再指向该对象时,计数器减 1。当计数器的值为 0 时,表明该对象没有任何引用指向它,就被认为是垃圾对象。
  2. 可达性分析法:从一组被称为 GC Roots 的对象开始,通过引用关系向下搜索,能够被搜索到的对象称为可达对象,这些对象是存活的;而不能被搜索到的对象则被认为是垃圾对象。

  • 要点
  1. 垃圾对象定义:不再被引用的对象即为垃圾对象。
  2. 方法优缺点:引用计数法实现简单,但存在循环引用的问题,即两个对象相互引用,导致它们的引用计数器永远不为 0,从而无法被回收;可达性分析法是目前主流的垃圾对象判断方法,能够有效解决循环引用的问题。

  • 应用

在 Java 中,对象的引用分为强引用、软引用、弱引用和虚引用。不同类型的引用对对象的存活时间有不同的影响。例如,强引用是最常见的引用类型,只要强引用存在,对象就不会被回收;软引用在系统内存不足时才会被回收,常用于实现缓存;弱引用在垃圾回收时会被直接回收;虚引用主要用于跟踪对象被垃圾回收的状态。

5. 什么可作为 GC Roots 的对象

  • 定义

GC Roots 是可达性分析法中作为起始点的对象集合,以下几种对象可以作为 GC Roots:

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象:当一个方法被调用时,会在虚拟机栈中创建一个栈帧,栈帧中的本地变量表可能会引用一些对象,这些对象可以作为 GC Roots。
  2. 方法区中类静态属性引用的对象:类的静态属性是属于类的,而不是属于某个对象的,因此这些静态属性引用的对象可以作为 GC Roots。
  3. 方法区中常量引用的对象:常量在程序运行期间是固定不变的,常量引用的对象也可以作为 GC Roots。
  4. 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象:当 Java 程序调用 Native 方法时,会在本地方法栈中创建栈帧,栈帧中引用的对象可以作为 GC Roots。

  • 原理

从 GC Roots 开始进行可达性分析,可以确定哪些对象是可达的,哪些对象是不可达的。GC Roots 是程序中正在使用的对象,它们引用的对象也被认为是有用的,不能被回收。通过这种方式,可以确保在垃圾回收过程中,不会误回收那些还在被使用的对象。

  • 要点
  1. 起始点作用:GC Roots 是垃圾回收的起始点,通过它可以构建出对象的引用关系图。
  2. 多种类型:不同类型的 GC Roots 代表了不同的程序上下文,涵盖了虚拟机栈、方法区和本地方法栈等。

  • 应用

在某些情况下,临时对象也可能成为 GC Roots,例如在垃圾回收过程中,正在被使用的对象可能会被标记为 GC Roots,以确保在回收过程中这些对象不会被错误地回收。此外,在 Java 中,类加载器也可以作为一种特殊的 GC Roots,因为类加载器会引用类的元数据和类的实例对象。

6. 有哪些 GC 算法

常见的 GC 算法有以下几种:

  1. 标记 - 清除算法(Mark - Sweep):该算法分为两个阶段,首先标记出所有需要回收的对象,然后在标记完成后统一回收所有被标记的对象。
  2. 标记 - 整理算法(Mark - Compact):同样先标记出需要回收的对象,然后将存活的对象向一端移动,最后清理掉端边界以外的内存。
  3. 复制算法(Copying):将可用内存按容量划分为大小相等的两块,每次只使用其中一块。当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
  4. 分代收集算法(Generational Collection):根据对象的存活周期将内存划分为不同的区域,一般分为新生代和老年代。新生代使用复制算法,老年代使用标记 - 清除或标记 - 整理算法。

  • 原理

不同的 GC 算法基于不同的内存使用场景和对象存活特性设计。例如,复制算法适用于对象存活率较低的场景,因为它只需要复制存活的对象,而不需要标记和清除操作;标记 - 整理算法适用于对象存活率较高的场景,因为它可以避免内存碎片的产生。

  • 要点
  1. 标记 - 清除算法:简单直接,但会产生内存碎片,随着时间的推移,可能会导致无法分配连续的大内存空间。
  2. 复制算法:实现简单,回收效率高,但需要额外的内存空间,且当对象存活率较高时,复制操作的开销会比较大。
  3. 标记 - 整理算法:可以避免内存碎片,但移动对象的操作会带来一定的性能开销。
  4. 分代收集算法:结合了不同算法的优点,根据对象的存活周期进行分区管理,是目前主流的垃圾回收算法。

  • 应用

不同的垃圾回收器采用了不同的 GC 算法组合,例如,Serial 收集器在新生代采用复制算法,在老年代采用标记 - 整理算法;CMS 收集器在老年代采用标记 - 清除算法。开发者可以根据应用程序的特点和性能需求选择合适的垃圾回收器和 GC 算法。

7. 什么是 Minor GC, Full GC

  1. Minor GC:也称为新生代 GC,指的是发生在新生代的垃圾回收动作。由于新生代中的对象大多生命周期较短,所以 Minor GC 非常频繁,一般回收速度也比较快。
  2. Full GC:也称为全局 GC,指的是发生在整个堆(包括新生代、老年代、永久代 / 元空间)的垃圾回收动作。Full GC 通常会导致应用程序出现较长时间的停顿,因为它需要回收整个堆的内存。

  • 原理

Minor GC 主要是为了回收新生代中不再使用的对象,当新生代的内存空间不足时,就会触发 Minor GC。Full GC 通常是在老年代空间不足、永久代 / 元空间不足或者调用 System.gc() 方法时触发。

  • 要点
  1. 回收区域:Minor GC 只回收新生代的内存;Full GC 回收整个堆的内存,包括新生代、老年代和永久代 / 元空间。
  2. 停顿时间:Full GC 的停顿时间比 Minor GC 长,因为它涉及的回收范围更广,操作更复杂。

  • 应用

频繁的 Full GC 会影响应用程序的性能,因此在开发过程中需要尽量避免 Full GC 的发生。可以通过调整堆内存的大小、优化对象的生命周期等方式来减少 Full GC 的频率。例如,合理设置新生代和老年代的比例,避免创建过多的大对象,及时释放不再使用的对象等。

8. 什么是 YGC

  • 定义

YGC 是 Young Generation Garbage Collection 的缩写,即新生代垃圾回收,与 Minor GC 是同一个概念。它主要负责回收新生代中的垃圾对象,由于新生代中的对象大多是朝生夕灭的,所以 YGC 发生的频率比较高。

  • 原理

当新生代中的 Eden 区或 Survivor 区内存不足时,就会触发 YGC。YGC 通常采用复制算法,将存活的对象复制到另一个 Survivor 区或老年代。

  • 要点
  1. 回收范围:YGC 只针对新生代进行垃圾回收。
  2. 性能特点:YGC 的回收速度相对较快,停顿时间较短,因为新生代中的对象存活率较低,复制操作的开销较小。

  • 应用

在监控 Java 应用程序的性能时,YGC 的频率和耗时是重要的指标。过高的 YGC 频率可能意味着新生代内存分配不合理,需要调整堆内存的大小或对象的生命周期。例如,如果 YGC 过于频繁,可以适当增大新生代的内存空间,减少对象进入老年代的概率。

9. 什么是 FGC

  • 定义

FGC 是 Full Garbage Collection 的缩写,即全局垃圾回收,与 Full GC 是同一个概念。它会对整个堆(包括新生代、老年代、永久代 / 元空间)进行垃圾回收,通常会导致应用程序出现较长时间的停顿。

  • 原理

FGC 通常在以下几种情况下触发:老年代空间不足、永久代 / 元空间不足、调用 System.gc() 方法、堆中产生了大对象等。FGC 会采用标记 - 清除或标记 - 整理算法来回收内存。

  • 要点
  1. 回收范围:FGC 会回收整个堆的内存,涉及的范围广,操作复杂。
  2. 性能影响:FGC 的停顿时间较长,会对应用程序的性能产生较大影响,因为在回收过程中,应用程序需要暂停执行。

  • 应用

为了减少 FGC 的发生,可以采取以下措施:合理调整堆内存的大小、避免创建大对象、及时释放不再使用的对象等。例如,在设计数据结构时,尽量避免使用过大的数组或集合,以减少大对象的产生。

10. 什么是 CMS

  • 定义

CMS(Concurrent Mark Sweep)是一种以获取最短回收停顿时间为目标的垃圾回收器,它基于标记 - 清除算法实现,主要针对老年代进行垃圾回收。CMS 收集器在 JDK 1.5 时期被引入,适用于对响应时间要求较高的应用程序。

  • 原理

CMS 收集器的工作过程分为四个阶段:

  1. 初始标记(Initial Mark):标记出所有直接与 GC Roots 关联的对象,这个阶段会导致应用程序出现短暂的停顿。
  2. 并发标记(Concurrent Mark):从初始标记阶段标记的对象开始,并发地遍历整个老年代,标记出所有需要回收的对象,这个阶段不会导致应用程序停顿。
  3. 重新标记(Remark):修正并发标记阶段因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段会导致应用程序出现短暂的停顿。
  4. 并发清除(Concurrent Sweep):并发地清除所有被标记的对象,这个阶段不会导致应用程序停顿。

  • 要点
  1. 目标优势:CMS 收集器的主要优点是停顿时间短,适合对响应时间要求较高的应用程序,如 Web 应用。
  2. 算法缺陷:CMS 收集器基于标记 - 清除算法,会产生内存碎片,随着时间的推移,可能会导致无法分配连续的大内存空间。
  3. 资源占用:CMS 收集器在并发标记和并发清除阶段会占用一部分 CPU 资源,可能会影响应用程序的性能,尤其是在 CPU 资源紧张的情况下。

  • 应用

由于 CMS 收集器存在内存碎片和占用 CPU 资源等问题,从 JDK 9 开始,CMS 收集器被标记为废弃,推荐使用 G1 收集器。G1 收集器结合了标记 - 整理和复制算法,避免了内存碎片的产生,并且可以更好地控制停顿时间,能够在不同的场景下提供更稳定的性能。

 

 友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读

https://download.csdn.net/download/ylfhpy/90523338 

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

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

相关文章

使用BootStrap 3的原创的模态框组件,没法弹出!估计是原创的bug

最近在给客户开发一个CRM系统,其中用到了BOOTSTRAP的模态框。版本是3。由于是刚开始用该框架。所以在正式部署到项目中前,需要测试一下,找到框架中的如下部分。需要说明的是。我用的asp.net mvc框架开发。测试也是在asp.net mvc环境下。 复制…

【Azure 架构师学习笔记】- Azure Networking(1) -- Service Endpoint 和 Private Endpoint

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Networking】系列。 前言 最近公司的安全部门在审计云环境安全性时经常提到service endpoint(SE)和priavate endpoint(PE)的术语,为此做了一些研究储备。 云…

Excel第41套全国人口普查

2. 导入网页中的表格:数据-现有链接-考生文件夹:网页-找到表格-点击→变为√-导入删除外部链接关系:数据-点击链接-选中连接-删除-确定(套用表格格式-也会是删除外部链接)数值缩小10000倍(除以10000即可&am…

VUE2导出el-table数据为excel并且按字段分多个sheet

首先在根目录下建一个文件夹export用来存储export.js import * as XLSX from xlsxfunction autoWidthFunc(ws, data) {// 设置每列的最大宽度const colWidth data.map(row > row.map(val > {var reg new RegExp([\\u4E00-\\u9FFF], g) // 检测字符串是否包含汉字if (v…

PDF文件转Markdown,基于开源项目marker

​ 首先我们来问下deepseek 为啥要选marker呢 基于深度学习,一看就逼格拉满。搞科研必备,效果应该不会太差。 看下官网 https://github.com/VikParuchuri/marker ​ 一看头像是个印度佬,自吹——又快又好。那就试试吧。 安装步骤 安装…

【蓝桥杯速成】| 9.回溯升级

题目一:组合综合 问题描述 39. 组合总和 - 力扣(LeetCode) 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返…

【uni-app】引用公共组件

目录 一、建立公共组件 1.1新建vue文件 1.2编写公共文件代码 1.3使用 注意事项 一、建立公共组件 1.1新建vue文件 在公共组件文件目录下新建所需要的功能文件 1.2编写公共文件代码 按需求写对应功能的代码 1.3使用 在需要使用的文件下引用公共组件 注意事项 想要使用s…

API-Arrays

Arrays 操作数组的工具类 1.tostring import java.util.Arrays;public class demo1 {public static void main(String[] args) {Integer[] arr {2, 3, 1, 5, 6, 7, 8, 4, 9};System.out.println(Arrays.toString(arr));//[2, 3, 1, 5, 6, 7, 8, 4, 9]} } 2.binarySearch 二…

尝试在软考62天前开始成为软件设计师-信息系统安全

安全属性 保密性:最小授权原则(能干活的最小权限)、防暴露(隐藏)、信息加密、物理保密完整性(防篡改):安全协议、校验码、密码校验、数字签名、公证 可用性:综合保障( IP过滤、业务流控制、路由选择控制、审计跟踪)不可抵赖性:数字签名 对称加密 DES :替换移位 3重DESAESR…

dsPIC33CK64MC105 Curiosity Nano|为高性能数字电源与电机控制而生

「dsPIC33CK64MC105 Curiosity Nano」面向高性能数字电源与电机控制而生 dsPIC33CK64MC105 Curiosity Nano 该评估套件是一个经济高效的硬件平台,用于评估dsPIC33CK系列高性能数字信号控制器(DSC)。该板采用 100 MHz dsPIC33CK64MC105 DSC&am…

《面向车险理赔的事故信息提取》开题报告

个人主页:大数据蟒行探索者 目录 一、选题的依据及意义 二、国内外研究概况及发展趋势 (1)车牌识别技术 (2)证件信息提取技术 (3)交通事故认定书文本提取 三、研究内容及实验方案 1.研究…

【AI神经网络】深度神经网络(DNN)技术解析:从原理到实践

引言 深度神经网络(Deep Neural Network, DNN)作为人工智能领域的核心技术,近年来在计算机视觉、自然语言处理、医疗诊断等领域取得了突破性进展。与传统机器学习模型相比,DNN通过多层非线性变换自动提取数据特征,解决…

EasyRTC轻量级Webrtc音视频通话SDK,助力带屏IPC在嵌入式设备中的应用

一、市场背景 随着人们生活水平的提高,对于家居安全和远程监控的需求日益增长,带屏IPCam不仅满足了用户实时查看监控画面的需求,还提供了诸如双向语音通话、智能报警等丰富的功能,极大地提升了用户体验。 此外,技术的…

预测数值型数据:回归

1.1 用线性回归找到最佳拟合直线 线性回归:优点:结果易于理解,计算上不复杂 缺点:对非线性的数据拟合不好 适用数据类型:数值型和标称型数据 回归的目的就是预测数值型的目标值。 回归的一般方法: &#…

【操作系统安全】任务3:Linux 网络安全实战命令手册

目录 一、基础网络信息获取 1. 网络接口配置 2. 路由表管理 3. 服务端口监控 二、网络监控与分析 1. 实时流量监控 2. 数据包捕获 3. 网络协议分析 三、渗透测试工具集 1. 端口扫描 2. 漏洞利用 3. 密码破解 四、日志审计与分析 1. 系统日志处理 2. 入侵检测 3…

5.4 位运算专题:LeetCode 137. 只出现一次的数字 II

1. 题目链接 LeetCode 137. 只出现一次的数字 II 2. 题目描述 给定一个整数数组 nums,其中每个元素均出现 三次,除了一个元素只出现 一次。请找出这个只出现一次的元素。 要求: 时间复杂度为 O(n),空间复杂度为 O(1)。 示例&a…

3. 轴指令(omron 机器自动化控制器)——>MC_SetPosition

机器自动化控制器——第三章 轴指令 11 MC_SetPosition变量▶输入变量▶输出变量▶输入输出变量 功能说明▶时序图▶重启动运动指令▶多重启运动指令▶异常 MC_SetPosition 将轴的指令当前位置和反馈当前位置变更为任意值。 指令名称FB/FUN图形表现ST表现MC_SetPosition当前位…

Python+Requests+Pytest+YAML+Allure接口自动化框架

GitHub源码地址(详细注释):源码 调试项目python自主搭建:附项目源码 一、项目介绍 本项目是基于 PythonRequestsPytestYAMLAllure 搭建的 接口自动化测试框架,用于对 REST API 进行测试。 框架的主要特点包括&#…

用 Python 也能做微服务?

一、Python 和微服务,是敌是友? Python 因其极强的开发效率与生态,一直是数据处理、AI、Web 开发的主力选手。但在“微服务”这个领域,它一直处于边缘地带: 服务注册 / 发现?🤷‍♂️ 没有统一…

Maya基本操作

基本操作 按住ALT键,左键旋转视角,中键平移视角,右键放大缩小视角。 按空格键切换4格视图。 导入FBX格式文件后,无贴图显示。 按6键开启。着色纹理显示 坐标轴相关 修改菜单-左键最上面的虚线。固定修改选项窗口。 选中物体…