面试 JVM 八股文五问五答第一期

面试 JVM 八股文五问五答第一期

作者:程序员小白条,个人博客

相信看了本文后,对你的面试是有一定帮助的!

⭐点赞⭐收藏⭐不迷路!⭐

1.JVM内存布局

Heap (堆区)

堆是 OOM 故障最主要的发生区域。它是内存区域中最大的一块区域,被所有线程共享,存储着几乎所有的实例对象、数组。

Java 堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC 堆”。从内存回收的角度来看,由于现在收集器基本都采用分代收集算法,所以 Java 堆中还可以细分为:新生代和老年代。再细致一点的有 Eden 空间、From Survivor 空间、To Survivor 空间等。从内存分配的角度来看,线程共享的 Java 堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)。不过无论如何划分,都与存放内容无关,无论哪个区域,存储的都仍然是对象实例,进一步划分的目的是为了更好地回收内存,或者更快地分配内存。

堆区的调整:通过设置如下参数,可以设定堆区的初始值和最大值,比如 -Xms256M -Xmx 1024M,其中 -X 这个字母代表它是 JVM 运行时参数,ms 是 memory start 的简称,中文意思就是内存初始值,mx 是 memory max 的简称,意思就是最大内存。

在通常情况下,服务器在运行过程中,堆空间不断地扩容与回缩,会形成不必要的系统压力所以在线上生产环境中 JVM 的 Xms 和 Xmx 会设置成同样大小,避免在 GC 后调整堆大小时带来的额外压力。

堆的默认空间分配:查看当前 JDK 版本所有默认的 JVM 参数:=======》java -XX:+PrintFlagsFinal -version

Java 虚拟机栈:

对于每一个线程,JVM 都会在线程被创建的时候,创建一个单独的栈。也就是说虚拟机栈的生命周期和线程是一致,并且是线程私有的。

栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构。栈帧存储了方法的局部变量表(局部变量表:定义为一个数字数组,用于方法参数和方法内部的局部变量,包括三种数据类型:8种基本数据类型+引用数据类型地址+returnAddress类型(指向一条字节码指令的地址) )、操作数栈(操作数栈主要用于保存运算过程中的的中间结果,同时作为计算过程中变量的临时的存储空间.)、动态链接(动态链接就是讲指令中的符号引用转化为真实的方法地址(直接引用)和方法返回地址等信息。每一个方法从调用至执行完成的过程,都对应着一个栈帧在虚拟机栈里从入栈到出栈的过程。

本地方法栈:

本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。在虚拟机规范中对本地方法栈中方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机(譬如 Sun HotSpot 虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈区域也会抛出 StackOverflowError 和 OutOfMemoryError 异常。

拓展:

  • 静态链接:当一个字节码文件被装载进JVM内部时,如果被调用的目标方法在编译器可知,且运行时期不变,这种情况下将调用方法的符号引用转换为直接引用的过程称之为静态链接.对应早期绑定(早期绑定就是指被调用的目标方法如果在编译期可知,且运行时期不变,即可将这个方法与所属的类型进行绑定,这样以来,由于明确了被调用的方法是哪一个,因此可以使用静态链接的方式将符号引用转换为直接引用).
  • 动态链接:如果被调用的方法在编译期无法被确定下来,只能够在程序运行期将调用方法的符号引用转换为直接引用,由于这种引用转换过程具备动态性,因此被称之为动态链接.对应晚期绑定(如果被调用方法在编译期无法被确定下来,只能在程序运行期根据实际的类型绑定相应的方法,这种绑定方式被称为晚期绑定).

程序计数器:

程序计数器(Program Counter Register)是一块较小的内存空间。是线程私有的。它可以看作是当前线程所执行的字节码的行号指示器

直接内存:

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区域。但是这部分内存也被频繁地使用,而且也可能导致 OutOfMemoryError 异常出现

Code Cache:

JVM 代码缓存是 JVM 将其字节码存储为本机代码的区域 。我们将可执行本机代码的每个块称为 nmethod。该 nmethod 可能是一个完整的或内联 Java 方法。

2.Java如何标记垃圾

Java中的垃圾回收是通过标记-清除算法实现的。当一个对象不再被任何引用指向时,它就可以被垃圾回收器回收。

在Java中,垃圾回收器通过可达性分析算法来标记垃圾对象。可达性分析算法是从一组被称为“GC Roots”的根对象开始遍历内存中的所有对象,任何能够被遍历到的对象都被认为是“存活”的对象,而未被遍历到的对象则被认为是“垃圾”对象。

Java中的GC Roots包括以下几种类型的对象:

  1. 虚拟机栈中引用的对象
  2. 方法区中静态属性引用的对象
  3. 方法区中常量引用的对象
  4. 本地方法栈中JNI(Java Native Interface)引用的对象

垃圾回收器会从GC Roots开始遍历内存中的所有对象,标记出所有被引用的对象,然后将没有被标记的对象视为垃圾对象进行回收。这个过程中,需要注意的是,垃圾回收器不能回收互相引用的对象,即使这些对象已经没有任何被引用的路径,因为它们之间仍然存在一条循环引用的路径,所以它们仍然被视为“存活”的对象。

需要注意的是,Java虚拟机的垃圾回收机制是自动的,程序员无法直接干预。但是,可以通过一些手段来优化垃圾回收的效率,比如尽量避免创建大量的临时对象,避免使用过多的finalize()方法等。

3.GC回收的是哪里?

因为虚拟机栈、本地方法栈、程序计数器是线程私有的,随着线程的消亡而消亡,方法结束或者线程结束时,内存自然就跟随着回收了。 GC回收的区域是堆和方法区,为什么回收这两个区域那,因为他们是线程共享的,即java程序中所有的线程都可以访问。

4.常见的垃圾回收算法有哪些?

**分代收集算法:**根据内存对象的存活周期不同,将内存划分成几块,java虚拟机一般将内存分成新生代和老生代,在新生代中,有大量对象死去和少量对象存活,所以采用复制算法,只需要付出少量存活对象的复制成本就可以完成收集;老年代中因为对象的存活率极高,没有额外的空间对他进行分配担保,所以采用标记清理或者标记整理算法进行回收;

**标记清除法:**第一步:利用可达性去遍历内存,把存活对象和垃圾对象进行标记;

第二步:在遍历一遍,将所有标记的对象回收掉;

特点:效率不行,标记和清除的效率都不高;标记和清除后会产生大量的不连续的空间分片,可能会导致之后程序运行的时候需分配大对象而找不到连续分片而不得不触发一次GC(垃圾回收);

**标记整理法:**第一步:利用可达性去遍历内存,把存活对象和垃圾对象进行标记;第二步:将所有的存活的对象向一段移动,将端边界以外的对象都回收掉;

特点:适用于存活对象多,垃圾少的情况;需要整理的过程,无空间碎片产生;

**复制算法:**将内存按照容量大小分为大小相等的两块,每次只使用一块,当一块使用完了,就将还存活的对象移到另一块上,然后在把使用过的内存空间移除;特点:不会产生空间碎片;内存使用率极低;

5.哪些情况下会出现FULLGC

  1. 调用 System.gc()

只是建议虚拟机执行 Full GC,但是虚拟机不一定真正去执行。不建议使用这种方式,而是让虚拟机管理内存。

  1. 未指定老年代和新生代大小,堆伸缩时会产生fullgc,所以一定要配置-Xmx、-Xms
  2. 老年代空间不足

老年代空间不足的常见场景比如大对象、大数组直接进入老年代、长期存活的对象进入老年代等。

为了避免以上原因引起的 Full GC,应当尽量不要创建过大的对象以及数组。

除此之外,可以通过 -Xmn 虚拟机参数调大新生代的大小,让对象尽量在新生代被回收掉,不进入老年代。

还可以通过 -XX:MaxTenuringThreshold 调大对象进入老年代的年龄,让对象在新生代多存活一段时间。

在执行Full GC后空间仍然不足,则抛出错误:java.lang.OutOfMemoryError: Java heap space

  1. JDK 1.7 及以前的(永久代)空间满

在 JDK 1.7 及以前,HotSpot 虚拟机中的方法区是用永久代实现的,永久代中存放的为一些 Class 的信息、常量、静态变量等数据。

当系统中要加载的类、反射的类和调用的方法较多时,永久代可能会被占满,在未配置为采用 CMS GC 的情况下也

会执行 Full GC。

如果经过 Full GC 仍然回收不了,那么虚拟机会抛出java.lang.OutOfMemoryError PermGen space

为避免以上原因引起的 Full GC,可采用的方法为增大Perm Gen或转为使用 CMS GC。

  1. 空间分配担保失败

空间担保,下面两种情况是空间担保失败:

1、每次晋升的对象的平均大小 > 老年代剩余空间

2、Minor GC后存活的对象超过了老年代剩余空间

注意GC日志中是否有promotion failed和concurrent mode failure两种状况,当出现这两种状况的时候就有可能会触发Full GC。

promotion failed 是在进行 Minor GC时候,survivor space空间放不下只能晋升老年代,而此时老年代也空间不足时发生的。

concurrent mode failure 是在进行CMS GC过程,此时有对象要放入老年代而空间不足造成的,这种情况下会退化使用Serial Old收集器变成单线程的,此时是相当的慢的。

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

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

相关文章

大数据毕业设计之前端03:logo、menu的折叠展开实现

关键字:BuildAdmin、pinia、logo、aside、menu、菜单折叠、Vue、ElementUI 前言 上一篇文章中,借助aside的实现讲了一些开发的小技巧,以及css的解读。本篇文章主要写一下如何填充aside的内容。 aside主要是由两个部分组成的:log…

数据结构与算法-Rust 版读书笔记-2线性数据结构-栈

数据结构与算法-Rust 版读书笔记-2线性数据结构-栈 一、线性数据结构概念 数组、栈、队列、双端队列、链表这类数据结构都是保存数据的容器,数据项之间的顺序由添加或删除时的顺序决定,数据项一旦被添加,其相对于前后元素就会一直保持位置不…

电脑入门基础知识

1.电脑键盘个数一般都是有多少个? 答:一般情况下,电脑键盘只有一个。但是,也有一些特殊的情况,例如游戏玩家可能会使用额外的游戏键盘,或者一些专业人士可能会使用多个键盘来提高工作效率。但是在大多数情…

[Spring~源码] ControllerAdvice揭秘

在Spring MVC中,我们经常使用ControllerAdvice注解,可以实现全局统一异常处理、全局数据绑定等功能。但是,它的实现原理是什么呢?在本文中,我们将深入探究ControllerAdvice的实现原理。 文章目录 什么是ControllerAdvi…

docker-compose.yml文件配置详解

简介 Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。 docker compose文件是一个yaml格式的文件&a…

【Hadoop_04】HDFS的API操作与读写流程

1、HDFS的API操作1.1 客户端环境准备1.2 API创建文件夹1.3 API上传1.4 API参数的优先级1.5 API文件夹下载1.6 API文件删除1.7 API文件更名和移动1.8 API文件详情和查看1.9 API文件和文件夹判断 2、HDFS的读写流程(面试重点)2.1 HDFS写数据流程2.2 网络拓…

学会面向对象经典练习题21道

1.面向对象练习:设计小狗类 需求: 抽象形成一个小狗类Dog 属性:名字name 年龄age 品种kind 主人host 价格price 功能: 跑run:无参,打印:小狗Dog跑的老快了~ 吃eat:参数int n&#x…

当MongoDB主键为String时,mongoTemplate无法根据id查询的问题

MongoDB推荐使用ObjectId作为主键,但国内的开发都知道,事情往往不如人所愿,当我们真的出现了“_id”主键的类型为String时,且还必须想用mongoTemplate.findOne或findList时,直接使用该方法会导致查询结果为空。 因为m…

https 协议

目录 加密方式 对称加密 非对称加密 非对称加密 非对称加密 非对称加密 对称加密 AC证书 AC证书内容 数据摘要 数据签名 在我们前面学习的http协议里面,我们发送的内容都是明文传输的,所以在安全上并不安全,但是在现在信息发达的时…

Java高级技术:优化性能与扩展性的最佳实践

标题:Java高级技术:优化性能与扩展性的最佳实践 摘要:本文将介绍Java中一些高级技术,以提高性能和代码的扩展性。本文不包括反射和并发编程,旨在帮助开发者进一步提升Java应用程序的质量和可维护性。 优化性能的最佳实…

面试题目总结(三)

1. Spring、Springboot、springMVC、Spring Cloud 的区别: Spring:Spring 是一个开源的、轻量级的Java框架,提供了丰富的功能和组件,用于构建企业级应用程序。Spring框架包含了很多模块,包括核心容器、数据访问、事物…

MATLAB算法实战应用案例精讲-【数模应用】漫谈机器学习(七)

目录 几个高频面试题目 机器学习算法工程师需要掌握哪些编程语言? 1.Python 2. C# 3.JavaScript 4. R 5.Java

Linux之Apache服务器安装及配置

一、Apache服务器简介 Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广泛使用。Apache曾经是世界使用排名第一的Web服务器软件&#xf…

VSCODE连接远程服务器

安装ssh插件 根据你的操作系统选择对应的版本进行下载和安装。 安装完成之后,启动vscode,选择左侧Extensions 选项卡,在输入框搜索 remote ,选择安装Remote-SSH插件。 安装完成之后会在左侧新增一个选项卡Remote Explorer&#xf…

肥猫游戏报价器|计价器|王者荣耀代练陪练等游戏报价器软件介绍说明

目录 1. 前言2. 软件著作权3. 软件使用说明3.1 进入软件3.2 用户登录3.3 首页3.4 报价器3.4.1 总体介绍3.4.2 王者报价器3.4.3 LOL手游报价器3.4.4 英雄联盟报价器3.4.5 云顶之弈报价器3.4.7 王者水晶报价器3.4.8 和平精英报价器3.4.9 蛋仔派对报价器3.4.10 穿越火线报价器3.4.…

kafka学习笔记--broker工作流程、重要参数

本文内容来自尚硅谷B站公开教学视频,仅做个人总结、学习、复习使用,任何对此文章的引用,应当说明源出处为尚硅谷,不得用于商业用途。 如有侵权、联系速删 视频教程链接:【尚硅谷】Kafka3.x教程(从入门到调优…

Linux mc命令教程:如何有效地使用mc命令(附案例详解和注意事项)

Linux mc命令介绍 mc命令是Linux中的一个视觉文件管理器,全称为Midnight Commander。它提供了一个用户友好的界面,使得在Linux环境中的文件和目录管理变得更加直观和方便。mc命令支持鼠标操作和颜色显示,同时也提供了一套菜单接口&#xff0…

TypeScript 常用高级类型

目录 前言: TypeScript 常用高级类型 基本概念 高级类型 1. 交叉类型(Intersection Types) 2. 联合类型(Union Types) 3. 映射类型(Mapped Types) 4. 条件类型(Conditional…

GGML 或GGUF的14种不同量化模式说明

查看 TheBloke/Llama-2–13B-chat-GGML 存储库中的文件,我们可以看到 14 种不同的 GGML 模型,对应于不同类型的量化。它们遵循特定的命名约定:“q” 用于存储权重的位数(精度) 特定变体。以下是所有可能的量化方法及其…

Pytorch-Transformer轴承故障一维信号分类(三)

目录 前言 1 数据集制作与加载 1.1 导入数据 第一步,导入十分类数据 第二步,读取MAT文件驱动端数据 第三步,制作数据集 第四步,制作训练集和标签 1.2 数据加载,训练数据、测试数据分组,数据分batch…