JVM高频面试题(2023最新版)

JVM面试题

1、JVM内存区域

在这里插入图片描述

Jvm包含两个子系统和两个组件。

1.1子系统

Class loader(类加载器):根据给定的全限定名类名(java.lang.object)来装载class文件到Runtime data area(运行时数据区)的method(方法区)。

Execution engine(执行引擎):执行classes中的指令。

Native Interface(本地接口):与native libraries交互,是其他编程语言交互的接口。

Runtime data area(运行时数据区域):JVM内存

作用

  • 通过编译器将Java代码转换为字节码
  • 类加载器(class loader)再将字节码加载到内存中(运行时数据区)的方法区(method)
  • 字节码文件只是JVM的一套指令集规范,不能直接交给底层操作系统执行,需要特定的命令解析器执行引擎(Execution engine),将字节码翻译成底层系统指令
  • 再交给CPU执行
  • 过程中需要调用其他语言的本地库接口(native interface)实现整个程序的功能

类的加载:将class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆上创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。

1.2 运行时数据区

在这里插入图片描述

程序计数器:当前线程所执行的字节码的行号指示器。通过改变这个计数器的值,选取下一条需要执行的字节码指令。

Java虚拟机栈:存储局部变量表、操作数栈、动态连接、方法出口等信息。(服务JAVA方法)

本地方法栈:为虚拟机Native方法服务的,这些方法底层是C语言编写,直接与操作系统对接的方法。

:内存中最大的一块,被所有线程共享,几乎所有对象实例都在这里分配内存。包括静态对象。

方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。

1.2.1 堆和栈的区别

物理地址

堆的物理地址分配对象是不连续的。性能较慢。在GC时考虑到不连续的分配,因此有各种算法(标记清除、复制、标记压缩、分代等)

栈使用的是数据结构中的栈,先进后出,物理地址分配时连续的,性能快。

内存分别

堆因为分配不是连续的,分配的内存在运行期才确认,大小不固定。

栈是连续的,分配的内存大小在编译器就确认,大小是固定的。

存放的内容

堆存放对象的实例和数组,更关注数据的存储。

栈存放局部变量,操作数栈,返回结果。更关注程序方法的执行。

可见度

堆对于整个应用程序共享、可见。

栈只对于线程可见,线程私有。生命周期和线程相同。

1.2.2 队列和栈的区别
  • 队列:入队,出队;栈:进栈,出栈。
  • 队列是队尾入队,队头出队,先进先出,两边都可操作;栈是先进后出,进栈出栈都在栈顶进行。
1.2.3 对象的创建过程
  • 虚拟机收到new指令,先检查常量池是否已加载对应的类
  • 如果没有,先执行相应的类加载(java文件转class,存入运行时数据区),类加载通过后分配内存
  • 若堆中的内存是绝对规整的,使用“指针碰撞”方式分配内存。
  • 若不是规整的,从空闲列表中分配
1.2.4 内存溢出异常

不再被使用的对象或变量一直被占据在内存中。理论上Java有GC垃圾回收机制,不再被使用的对象会被GC自动回收。但还是存在内存泄漏问题。

原因:长生命周期的对象持有短生命周期对象的引用就会导致内存泄漏。

2 垃圾收集器

2.1 垃圾回收机制

Java中,由虚拟机自行执行对象的内存释放。有一个垃圾回收线程,低优先级,在虚拟机空闲或当前堆内促不足时,触发执行,扫描那些没有被任何引用的对象,并将它们添加到需要回收的集合中,进行回收。

2.2 GC

Gabage Collection 垃圾收集,忘记或错误的内存回收会导致程序或系统的不稳定甚至崩溃。

Java提供的GC功能可以自动检测对象是否超过作用域,从而达到自动回收内存的目的。

垃圾回收的优点

  • 编写程序时,不需要考虑内存管理问题
  • Java中的对象不再有“作用域”的概念,只有引用的对象才有“作用域”
  • 垃圾回收机制有效防止了内存泄漏,有效的使用可使用的内存
  • 作为一个单独的低级别的线程运行,在不可预知的情况下对堆中已经死亡或长时间没有用过的对象进行清除和回收
  • 程序员不能实时对某个对象或所有对象调用垃圾回收器进行回收
  • 垃圾回收有分代复制、标记、增量垃圾回收

垃圾回收基本原理

对于GC来说,当对象被创建后,GC就开始监控这个对象的地址、大小、及使用情况。

通常,GC采用向图的方式记录和管理堆中的对象。通过确定哪些对象是“可达的”。当GC确定一些对象为“不可达”时,GC就有责任回收这些内存空间。

可以通过System.gc(),通知GC运行,但并不保证GC一定会运行。

怎么判断对象是否可以被回收?

  • 引用计数器法:为每个对象创建一个引用计数,有对象引用时+1,引用被释放时-1,当计数器为0时,就可以回收了。但是不能解决循环引用的问题
  • 可达性分析算法:GC Roots开始向下搜索,当一个对象到GC Roots没有任何引用链相连时,则证明可以被回收

2.3 垃圾回收算法

标记-清除法:标记无用的对象,进行清除。(其他算法几乎都是在其上进行改进)

优点:实现简单,不需要对象进行移动。

缺点:效率低,产生大量不连续的内存碎片,提高了垃圾回收的频率。

  • 标记阶段:标记出可以回收的对象
  • 清除阶段:回收被标记的对象所占用的空间

复制算法:将内存划分为两个相等的区域,每次只使用其中一个。每次遍历单个区域,将存活的对象复制到另一个区域,再清除当前区域。

优点:按顺序分配内存,运行效率高,不用考虑内存碎片

缺点:可用的内存大小只要原来的一半,对存活率高的对象频繁复制

标记-整理算法:在新生代可以使用复制算法,老年代不适合(存活频率高)。标记整理算法在标记回收对象后,将所有存活的对象压缩到内存的一段,紧凑排列,再对边界外的内存进行回收。

优点:解决了标记清理算法存在内存碎片的问题

缺点:仍需要进行局部的对象移动,一定程度上降低了效率

分代收集算法:根据对象存活周期,将内存划分为几块:年轻代、老年代、永久代。(jdk1.8后,删除了永久代,增加了元数据区)

2.4 垃圾回收器

在这里插入图片描述

Serial收集器(复制算法):新生代单线程收集器,标记和清理都是单线程,优点是简单高效。收集器回收时会暂停业务线程。

ParNew收集器(复制算法):新生代并行收集器,Serial收集器的多线程版本,多核CPU环境下比Serial性能更好。GC线程和业务线程并行。

Parallel Scavenge(复制算法):新生代并行收集器,追求高吞吐量,高效利用CPU。尽快完成程序的运算任务。jdk1.8默认收集器。GC线程和业务线程并行。

Serial Old收集器 (标记-整理算法):老年代单线程收集器,Serial收集器的老年代版本。收集器回收时会暂停业务线程。

Parallel Old收集器(标记-整理算法):老年代并行收集器,吞吐量优先,Parallel Scavenge的老年代版本。jdk1.8默认收集器。GC线程和业务线程并行。

CMS收集器(标记-清除算法):老年代并行收集器,以获取最短回收停顿时间为目标的收集器,高并发、低停顿,追求最短GC回收停顿时间。牺牲了吞度量来获得最短的停顿时间,适用于服务器响应速度高要求的应用上。因为是基于标记-清除算法,会出现大量内存碎片,此时CMS会临时采用Serial Old回收器进行垃圾清除,同时性能会下降。GC线程和业务线程并行。在启动 JVM 的参数加上“-XX:+UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器。

G1收集器(标记-整理算法):Java堆并行收集器,由jdk1.7提供,基于标记整理-算法,回收范围为整个堆,而不再分新生代和老年代。区域上使用了分区算法。一边清理一部分区域,一边占用一部分区域,特别大的对象放Humongous区域,也不够了开始FullGC。

ZGC(颜色算法):分区更灵活,逻辑上部分带。每次找到特别满的区域进行清除。

垃圾回收器工作流程

新生代:老年代=1:2

新生代使用复制-算法,本身也分三个区,Eden、To Survivor、From Survivor。默认8:1:1

  • Eden+From Survivor存活的对象放入To Survivor
  • 清空Eden+From Survivor分区
  • From Survivor和To Survivor分区交换

每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄都+1,当年龄达到15(默认的)时,升级为老年代,大的对象直接放入老年代。

老年代这边,当空间占用达到某一个阈值之后,触发Full GC,此时一般使用标记整理算法。

对象优先分配到新生代的Eden区,Eden区空间不够时,进行Minor GC,还不够,则分配到老年代。

Minor GC非常频繁,回收速度也快。大对象(需要大量连续内存空间的对象)直接进入老年代。

3、虚拟机类加载机制

3.1 简述

虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、解析和初始化,最终形成虚拟机可以直接使用的Java类型。

3.2 JVM加载Class文件的原理机制

隐式装载:程序运行过程中,碰到new等方式创建对象时,调用类装载器加载对应类到JVM中。

显示装载:通过class.forname()等方法,显示加载需要的类。

动态加载,保证基类完全加载,其他类需要的时候才加载。

3.3 类加载器

实现通过类的权限定名获取该类的二进制字节流的代码块

  1. 启动类加载器,加载Java核心类库,无法被程序直接引用。Java_HOME/lib/目录中的,被 -Xbootclasspath参数指定路径的类库。
  2. 扩展类加载器,加载Java的扩展库,Java虚拟机的实现会提供一个扩展库目录。JDK的安装目录的jre/lib/ext子目录(扩展目录)或Java. ext. dirs系统变量指定的路径中的所有类库。
  3. 系统类加载器,根据Java应用的类路径(ClassPath)来加载Java类。通常Java应用的类都是它加载的。可通过ClassLoader.getSystemClassLoader()获取它。
  4. 用户自定义类加载器,通过继承java.lang.ClassLoader类实现。

3.4 类装载的过程

  • 加载:根据路径找到对应的class文件导入。
  • 验证:检查加载的class文件的正确性。
  • 准备:给类中的静态变量分配内存空间。
  • 解析:虚拟机将常量池中的符号引用替换成直接引用的过程。
  • 初始化:对静态变量和静态代码块执行初始化工作。

3.5 双亲委派

如果一个类加载器收到了类加载的请求,首先不会自己去加载,

而是委派给父类加载器,这样所有的加载请求都会传到顶层的启动类加载器,

当父加载无法完成加载(搜索范围中没找到)时,子加载器才去尝试加载。

启动类加载器=》扩展类加载器=》系统类加载器=》自定义类加载器。

3.5.1 优点
  • 避免类重复加载(唯一性),只会在一个类加载器加载。
  • 安全性,保证Java核心类库的安全,比如自己又写了一个java.lang.String,优先会去加载核心类库中的。
  • 为模块化开发提供了基础支持,如果使用多个第三方库,可能存在同名的类。使用双亲委派机制可以保证不同的类加载器只加载自己的类,避免类名冲突。

4、JVM调优

4.1 工具

JDK的bin目录下,自带了很多监控工具。

jconsole:用于对JVM中内存、线程和类等进行监控。

jvisualvm:内存快照、线程快照、程序死锁、监控内存变化、GC变化等。

4.2 参数

  • -Xms2g:初始化推大小为 2g;
  • -Xmx2g:堆最大内存为 2g;
  • -XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;
  • -XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
  • –XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
  • -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
  • -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
  • -XX:+PrintGC:开启打印 gc 信息;
  • -XX:+PrintGCDetails:打印 gc 详细信息。
    urvivor 比例为 8:2;
  • –XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
  • -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
  • -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
  • -XX:+PrintGC:开启打印 gc 信息;
  • -XX:+PrintGCDetails:打印 gc 详细信息。

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

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

相关文章

医院安全(不良)事件报告系统源码 支持二次开发、支持源码交付

医疗不良事件报告系统源码旨在建立全面的、统一的医疗不良事件标准分类系统和患者安全术语,使不良事件上报管理更加标准化和科学化。通过借鉴国内外医疗不良事件报告系统的先进经验,根据医疗不良事件的事件类型、处理事件的不同部门,灵活设置…

【python 的各种模块】(8) 在python使用matplotlib和wordcloud库来画wordcloud词云图

目录 目标:用python画出,网上流行的wordcloud词云图 1 准备工作 1.1环境准备 1.1.1安装步骤 1.2 资源准备 1.2.1 文本文件内容如下 1.2.2 图片资源 2 代码测试 2.1 第一版代码和效果 2.1.1 代码和效果 2.1.2 一般plt里解决中文乱码问题 2.1…

Java中XML的解析

1.采用第三方开元工具dom4j完成 使用步骤 1.导包dom4j的jar包 2.add as lib.... 3.创建核心对象, 读取xml得到Document对象 SAXReader sr new SAXReader(); Document doc sr.read(String path); 4.根据Document获取根元素对象 Element root doc.getRootElement(); …

win11 or win10 安装Ubuntu 22.04.3 LTS 子系统

** 1. 修改电脑的相关设置 ** 1.在系统设置中的开发者人员模式,设置为开启状态 2. 在控制面板中的程序中的启用或者关闭windows功能下,开启(勾选)子系统模式,然后重启电脑 2. 在Microsoft store中下载子系统&…

深度学习 | DRNN、BRNN、LSTM、GRU

1、深度循环神经网络 1.1、基本思想 能捕捉数据中更复杂模式并更好地处理长期依赖关系。 深度分层模型比浅层模型更有效率。 Deep RNN比传统RNN表征能力更强。 那么该如何引入深层结构呢? 传统的RNN在每个时间步的迭代都可以分为三个部分: 1.2、三种深层…

算法与数据结构--特殊有序集的线性时间排序算法

一.计数排序算法 基本思想:统计每个输入元素的个数,然后根据这些计数值重构原数组。 使用范围:需要知道元素大小范围,就是最大值是多少。 【排序算法】计数排序_哔哩哔哩_bilibili 二.基数排序 使用场景:只适用于…

Laravel的知识点

1.{{ }} 是在 HTML 中内嵌 PHP 的 Blade 语法标识符,表示包含在该区块内的代码都将使用 PHP 来编译运行。 2.两种写法 3.return void 在这段注释中,"return void" 表示该函数或方法没有返回值。这意味着它执行某些操作或任务,但…

论文阅读《Rethinking Efficient Lane Detection via Curve Modeling》

目录 Abstract 1. Introduction 2. Related Work 3. BezierLaneNet 3.1. Overview 3.2. Feature Flip Fusion 3.3. End-to-end Fit of a Bezier Curve 4. Experiments 4.1. Datasets 4.2. Evalutaion Metics 4.3. Implementation Details 4.4. Comparisons 4.5. A…

使用克魔助手进行iOS数据抓包和HTTP抓包的方法详解

摘要 本文博客将介绍如何在iOS环境下使用克魔助手进行数据抓包和HTTP抓包。通过抓包,开发者可以分析移动应用程序的网络请求发送和接收过程,识别潜在的性能和安全问题,提高应用的质量和安全性。 引言 在移动应用程序的开发和测试过程中&am…

Linux磁盘与文件系统管理

目录 在linux系统中使用硬盘 磁盘的数据结构 磁盘接口类型 字母含义 MBR磁盘分区 分区类型 分区的缺点 文件系统的 文件系统有什么作用 文件系统的修复 检测并确认新磁盘 参看磁盘信息 查看磁盘信息 添加磁盘 查看添加磁盘情况:sda系统磁盘&#xff…

每周一算法:区间覆盖

问题描述 给定 N N N个闭区间 [ a i , b i ] [a_i,b_i] [ai​,bi​],以及一个线段区间 [ s , t ] [s,t] [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。 输出最少区间数,如果无法完全覆盖则输出 − 1 -1 −1。 输入格式…

【自然语言处理】第3部分:识别文本中的个人身份信息

自我介绍 做一个简单介绍,酒架年近48 ,有20多年IT工作经历,目前在一家500强做企业架构.因为工作需要,另外也因为兴趣涉猎比较广,为了自己学习建立了三个博客,分别是【全球IT瞭望】,【…

解决Hive在DataGrip 中注释乱码问题

注释属于元数据的一部分,同样存储在mysql的metastore库中,如果metastore库的字符集不支持中文,就会导致中文显示乱码。 不建议修改Hive元数据库的编码,此处我们在metastore中找存储注释的表,找到表中存储注释的字段&a…

软件测试/测试开发丨Python学习笔记之基本数据类型与操作

一、变量 1、变量的定义: a. 在python中,变量是一种存储数据的载体。计算机中的变量是实际存在的数据或者说是存储器中存储数据的一块内存空间; b.变量的值可以被读取和修改。 2、命名规则: a.变量名由字母(广义的Unic…

Python 常用模块Logging

Python 常用模块Logging 【序言】 logging模块是专门用来做日志记录的模块 【一】日志等级 默认打印结果到终端上 CRITICAL 50 # 致命错误 ERROR 40 # 错误 WARNING 30 # 警告 INFO 20 # 消息 DEBUG 10 # 调试 NOTSET 0 # 不设置示例: 默认级别为…

Unity引擎有哪些优点

Unity引擎是一款跨平台的游戏引擎,拥有很多的优点,如跨平台支持、强大的工具和编辑器、灵活的脚本支持、丰富的资源库和强大的社区生态系统等,让他成为众多开发者选择的游戏开发引擎。下面我简单的介绍一下Unity引擎的优点。 跨平台支持 跨…

自动化网络故障修复管理

什么是故障管理 故障管理是网络管理的组成部分,涉及检测、隔离和解决问题。如果实施得当,网络故障管理可以使连接、应用程序和服务保持在最佳水平,提供容错能力并最大限度地减少停机时间。专门为此目的设计的平台或工具称为故障管理系统。 …

WPF实战项目二十二(客户端):首页添加备忘录与待办事项

1、在View文件夹下新建文件夹Dialog&#xff0c;新建View&#xff1a;AddMemoView、AddToDoView <UserControlx:Class"WPFProject.Views.Dialogs.AddToDoView"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://s…

推荐五款简洁而实用的工具,值得你尝试

​ 分享快乐是生活中美好的瞬间&#xff0c;而分享简单巧妙的工具也能令我愉悦。这五款工具简洁而实用&#xff0c;值得你尝试。 1.视频播放器——Potplayer Potplayer是一款视频播放器&#xff0c;支持DXVA、CUDA和QuickSync等硬件加速技术&#xff0c;提供高效的视频播放性…

关于Java并发、JVM面试题

前言 之前为了准备面试&#xff0c;收集整理了一些面试题。 本篇文章更新时间2023年12月27日。 最新的内容可以看我的原文&#xff1a;https://www.yuque.com/wfzx/ninzck/cbf0cxkrr6s1kniv 并发 进程与线程的区别 线程属于进程&#xff0c;进程可以拥有多个线程。进程独享…