JVM面试总结

news/2024/4/19 16:42:23/文章来源:https://blog.csdn.net/Array_new/article/details/129174466

文章目录

        • 栈帧中存放的信息:
        • 对象的创建过程
        • 对象的内存布局?
        • 对象的访问定位方式?
        • 如何判断对象已死?
        • 可以作为GC Root的点:
        • 谈一下引用
        • 对象再被回收时如何逃脱?
        • 回收方法区
        • 如何判断常量是否废弃?
        • 垃圾回收算法及其优缺点
        • Full GC的触发条件
        • Serial垃圾收集器:
        • ParNew收集器:
        • Parallel Scavenge收集器:
        • Serial Old收集器:
        • Parallerl Old收集器:
        • CMS收集器:
        • 增量式并发收集器(CMS的变种):
        • G1垃圾回收器:
        • 低延迟垃圾收集器:
        • Shenandoah 收集器:
        • 内存分配的规则:
        • Class文件结构:
        • 类加载机制:
        • 双亲委派模型:
        • 破环双亲委派模型:
        • 运行时栈帧结构

栈帧中存放的信息:

存储局部变量 表、操作数栈、动态连接、方法出口等信息

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

JDK7把永久代的字符串常量池、静态变量等移出

描述为堆逻辑的一部分

对象的创建过程

  1. 判断对象对应的类是否加载、链接、初始化

    没有将执行类加载过程

  2. 为对象分配内存

    • 指针碰撞(内存规整)

      所有被使用过的内存都被放在一边,空闲的内存被放在另一边,中间放着 一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间方向挪动 一段与对象大小相等的距离

    • 空闲列表(内存不规整)

      虚拟机就必须维护一个列表,记录上哪些内存块是可 用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的 记录

  3. 处理并发安全问题

    • 对分配内存空间的动作进行同步处理

      CAS加失败重试保证操作的原子性

    • 把分配的内存的动作按照线程划分在不同的空间中

      即每个 线程在 Java 堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)

  4. 初始化分配到的空间

  5. 设置对象的对象头

    对对象进行必要的设置:哪个类的实例、 如何才能找到类的元数据信息、对象的哈希码(实际上对象的哈希码会延后到真正调用 Object::hashCode()方法时才计算)、对象的 GC 分代年龄等信息。

  6. 执行init方法进行初始化

对象的内存布局?

  1. 对象头

    • 存储对象自身的运行时数据(Mark Word)

      哈希码

      GC分代年龄

      锁状态标识

      线程持有的锁

      偏向线程ID

      偏向时间戳

    • 类型指针

      对象指向它的类型元数据的指针,Java 虚拟机通过这个指针来确定该对象是哪个类的实例。

  2. 实例数据

    是对象真正存储的有效信息

    即我们在程序代码里面所定义的 各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录 起来。

  3. 对齐填充

    不是必然存在的,也没什么特别的含义,仅仅起到占位符的作用

对象的访问定位方式?

  1. 句柄访问

    reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自 具体的地址信息

在这里插入图片描述

好处:reference中存储稳定句柄地址,对象被移动(垃圾收集时移动对象很普遍)时只会改变句柄中实例数据指针即可,reference本身不需要被修改

  1. 直接指针(HotSpot采用)

在这里插入图片描述

直接指针是局部变量表中的引用,直接指向堆中的实例,在对象实例中有类型指针,指向的是方法区中的对象类型数据

好处:速度更快,节省了一次指针的开销

如何判断对象已死?

  1. 引用计数算法

    优点:实现简单,垃圾对象便于辨识;判定效率高,回收没有延迟性。

    缺点:(1)(空间开销)他需要单独的字段存储计数器,这样的做法增加了存储空间的开销。

    ​ (2)(时间开销)每次赋值都需要更新计数器,伴随着加法和减法操作,这增加了时间开销。

    ​ (3)(循环引用)引用计数器还有一个严重的问题,即无法处理循环引用的问题,这是一条致命的缺陷,导致在Java回收的垃圾回收器中没有使用这类算法。

  2. 可达性分析算法

    优点:解决了不能循环引用的问题

    缺点:多线程情况下会造成误报或者漏报

可以作为GC Root的点:

  • 虚拟机栈中(栈帧中的本地变量表)中引用的对象
  • 在方法区中类静态属性引用的对象
  • 在方法区中常量引用的对象
  • 本地方法中JNI引用的对象
  • 虚拟机内部的引用
  • 所有同步锁持有的对象
  • 反映Java虚拟机内部情况的JMXBean、JVMTI 中注册的回调、本地代码缓存等。

谈一下引用

  1. 强引用

    是指在程序代码之中普遍存在的引用赋值,即类 似“Object obj=new Object()”这种引用关系

  2. 软引用

    用来描述一些还有用,但非必须的对象

  3. 弱引用

    用来描述那些非必须对象,但是它的强度比软引用更弱一些,被弱引 用关联的对象只能生存到下一次垃圾收集发生为止。

  4. 虚引用

    为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时 收到一个系统通知

  5. 终结器引用

对象再被回收时如何逃脱?

至少经过俩次标记过程:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,它将会被第一次标记,随后进行筛选,筛选的条件是此对象是否有必要执行finalize()方法,假如没有覆盖或者已经被虚拟机调用过,那么会被视为“没有必要执行”

如果有必要执行finalize()方法,会放置在一个F-Queue队列之中,并在稍后由一条虚拟机自动建立的、低调度优先级的优先级的Finalizer线程去执行finalize()方法。

finalize()方法是对象逃 脱死亡命运的最后一次机会,稍后收集器将对 F-Queue 中的对象进行第二次小规模的标 记,如果对象要在 finalize()中成功拯救自己——**只要重新与引用链上的任何一个对象建 立关联即可,譬如把自己(this 关键字)赋值给某个类变量或者对象的成员变量,**那在 第二次标记时它将被移出“即将回收”的集合。

回收方法区

方法区主要回收:废弃的常量和不再使用的类型。

如何判断常量是否废弃?

三个条件:

  • 该类的所有实例都已被回收
  • 加载该类的类加载器已经被回收
  • 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类

垃圾回收算法及其优缺点

标记-清除算法

标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对 象,也可以反过来,标记存活的对象,统一回收所有未被标记的对象。

缺点:

  • 执行效率不稳定
  • 内存空间碎片化

标记复制算法(“半区复制”)

它将可用内存按容量划分为大小相等的两块,每次只使用 其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后 再把已使用过的内存空间一次清理掉。

优点:

  • 实现简单
  • 运行高效

缺点:

  • (浪费空间,内存使用率低)产生大量的内存开销内存缩小为原来的一半

标记-整理算法

优点:解决了内存碎片化的问题

缺点:开销大

GC Roots主要在全局性的引用(常量或类静态属性)与执行上下文(栈帧的本地变量表)中

分代收集算法

  • 把一个内存分成多个区域,不同的区域使用不同的回收算法去回收。

增量算法

  • 每次只收集一小片区域内存空间的垃圾,这样就可以减少系统的停顿。

Full GC的触发条件

  • 老年代空间不足(第一是真的不足,第二是内存碎片化)
  • 元空间不足
  • 在某一次新生代回收之后要晋升到老年代对象所占用空间大于老年代的剩余空间
  • 显示调用了System.gc();

Serial垃圾收集器:

特点:串行垃圾收集器

优点:单线程收集效率高

​ 对于内存资源受限的环境,额外内存消耗最小

​ 对于单核处理器或处理器核心数较少的来说,没有线程交互的开销,单线程能做到最高效率

缺点:停顿时间长

ParNew收集器:

特点:Serial的并行版本

Parallel Scavenge收集器:

特点:为达到一个可控制的吞吐量(吞吐量优先收集器)

优点:有较好的吞吐量

缺点:

Serial Old收集器:

Serial的老年代版本

Parallerl Old收集器:

Parallel Scavenge 收集器的老年代版本

CMS收集器:

基于标记清除算法实现的

特点:获取最短的停顿时间给用户较好的体验,并发低停顿收集器

无法处理浮动垃圾,可能导致失败导致STW的Full GC

初始标记–并发标记–重新标记–并发清除

缺点:对处理器资源比较敏感,并发阶段会导致应用程序变慢,总吞吐量降低

收集结束会产生大量的空间碎片

增量式并发收集器(CMS的变种):

垃圾收集的过程会更长,减少了对用户程序的影响(已废弃)

G1垃圾回收器:

优点:不会产生空间碎片,可以精确地控制停顿

初始标记–并发标记–最终标记–筛选回收

内存占用方面:G1的记忆集所占的内存更多

执行负载角度:G1垃圾回收实现的异步处理

低延迟垃圾收集器:

Shenandoah 收集器:

九个阶段

内存分配的规则:

  • 对象优先在 Eden 分配
  • 大对象直接进入老年代
  • 长期存活的对象将进入老年代
  • 动态对象年龄判定:如果在 Survivor 空间中相同年龄所有对象大小的总和大于 Survivor 空间的 一半,年龄大于或等于该年龄的对象就可以直接进入老年代
  • 空间分配担保

Class文件结构:

魔数与Class文件的版本

常量池

访问标识

类索引、父类索引与接口索引集合

字段表集合

类加载机制:

(加载过程)生命周期:

  • 加载:

    • 通过一个类的全限定名来获取定义此类的二进制字节流。
    • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
    • 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种 数据的访问入口。
  • 验证

    • 文件格式验证:字节流是否符合Class文件格式规范

    • 元数据验证:对字节码进行语义分析,保证符合java语言规范

    • 字节码验证:通过数据流分析和控制 流分析,确定程序语义是合法的、符合逻辑的。

    • 符号引用验证:校验行为发生在虚拟机将符号引用转化为直接引用的时候,是对类自身 以外(常量池中的各种符号引用)的各类信息进行匹配性校验

      通俗来说就是,该类是 否缺少或者被禁止访问它依赖的某些外部类、方法、字段等资源。

  • 准备:正式为类中定义的变量(即静态变量,被 static 修饰的变量)分配内存 并设置类变量初始值

  • 解析: Java 虚拟机将常量池内的符号引用替换为直接引用

    • 符号引用:符号引用以一组符号来描述所引用的目标,符 号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可
    • 直接引用:直接引用是可以直接指向目标的指针、相对偏移量 或者是一个能间接定位到目标的句柄
  • 初始化:根据程序员通过程序编码制定的主观计划去初始化类变量和其他资源

  • 使用

  • 卸载

双亲委派模型:

在这里插入图片描述

双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会 自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加 载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有 当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时, 子加载器才会尝试自己去完成加载

破环双亲委派模型:

  • 在JDK1.2以前,JDK 1.2 之后的 java.lang.ClassLoader 中添加一个新的 protected 方法 findClass(), 并引导用户编写的类加载逻辑时尽可能去重写这个方法

​ 按照 loadClass()方法的逻辑,如果父类加载失败,会自动调用 自己的 findClass()方法来完成加 载

​ 这样既不影响用户按照自己的意愿去加载类,又可以保证新写 出来的类加载器是符 合双亲委派规则的。

  • 引入了上下文类加载器

    这个类加载器可以通过 java.lang.Thread 类的 setContext-ClassLoader()方法进行设置,如果创建线程时还未设置,它将会从父线程中继 承一个,如果在应用程序的全局范围内都没有设置过的话,那这个类加载器默认就是应 用程序类加载器。

  • 代码热替换、模块热部署

运行时栈帧结构

  • 局部变量表:是一组变量值的存储空间,存放方法参数和方法内部定义的局部变量

    以变量槽为最小单位

  • 操作数栈

  • 动态连接

  • 方法返回地址

  • 附加信息

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

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

相关文章

Redis的安装部署和配置文件的修改

1、准备安装环境 由于 Redis 是基于 C 语言编写的,因此首先需要安装 Redis 所需要的依赖: yum install -y gcc tcl gcc-c make 2、上传安装文件 将下载好的 redis-6.2.7.tar.gz 安装包上传到虚拟机的任意目录(一般推荐上传到 /usr/local/s…

Mysql 索引(三)—— 不同索引的创建方式(主键索引、普通索引、唯一键索引)

了解了主键索引的底层原理,主键索引其实就是根据主键字段建立相关的数据结构(B树),此后在使用主键字段作为条件查询时,会直接根据主键查找B树的叶子结点。除了主键索引外,普通索引和唯一键索引也是如此&…

stm32f103封装 入门教学(一)LED程序CubeMX

本文代码使用 HAL 库。 文章目录前言一、LED 原理图二、CubeMX创建工程三、LED 相关函数1. 输出电平函数:2. 延时函数:3. 翻转电平函数:四、详细代码实验现象 :总结代码 源码:前言 从这篇文章开始,我们讲解…

了解Axios及其运用方式

Axios简介 axios框架全称(ajax – I/O – system): 基于promise用于浏览器和node.js的http客户端,因此可以使用Promise API 一、axios是干啥的 说到axios我们就不得不说下Ajax。在旧浏览器页面在向服务器请求数据时,…

醒醒吧,外包测试哪有前途,你只是一块干电池而已,随时会被替换掉

我25岁的时候,外包测试,薪资13.5k,人在深圳。 内卷什么的就不说了,而且人在外包那些高级精英年薪大几十的咱也接触不到,就说说外包吧。假设以我为界限,25岁一线城市13.5k,那22-24大部分情况下是…

URP渲染管线光照机制剖析

上一节通过剖析URP 摄像机了解摄像机的机制,本节来分析URP的光照的主要机制,并通过与内置的向前渲染管线做对比,来比较它们的与不同。 对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些…

小程序电商商城怎么搭建?

做电商的企业商家都会首先搭建好自己的电商商城,尤其是现在小程序盛行的时代,小程序电商商城更是做电商的企业商家的必备媒介。那么小程序电商商城怎么搭建?下面给大家说说一些流程作为参考。 一、准备事项 搭建小程序电商商城,…

打不过就拉拢!ChatGPT和MidJourney已经成我小秘书!太爽了

大家好,我是晓衡。这两周,我战斗力爆棚了!每天大概睡了四~五个小时,而且中午也没有休息过,但精神却还很亢奋。直到周一下午,身体才有种被掏空的感觉,晚上 10 点就睡了。可能是兴奋劲还在&#x…

git 的使用方法(上 - 指令)

目录前言:一、Git 是什么?二、SVN与Git的最主要的区别?三、Git 安装四、git 配置1. 创建仓库 - repository2. 配置3. 工作流与基本操作五、Git 的使用流程1. 仓库中创建 1.txt文件2. 查看工作区的文件状态3. 添加工作区文件到暂存区4. 创建版…

蓝桥杯:聪明的猴子

题目链接:聪明的猴子https://www.lanqiao.cn/problems/862/learning/ 目录 题目描述 输入描述 输出描述 输入输出样例 运行限制 解题思路: 最小生成树 AC代码(Java): 课后练习: 题目描述 在一个热带雨林中生存…

C++11 条件变量(condition_variable)

一、总述 在C11中,我们可以使用条件变量(condition_variable)实现多个线程间的同步操作;当条件不满足时,相关线程被一直阻塞,直到某种条件出现,这些线程才会被唤醒。 主要成员函数如下&#x…

【java】Spring Cloud --Spring Cloud Alibaba 微服务解决方案

文章目录1、Spring Cloud Alibaba 是什么先说说 Spring CloudSpring Cloud Alibaba和Spring Cloud 的区别和联系Spring Cloud Alibaba2、Spring Cloud Alibaba 包含组件阿里开源组件阿里商业化组件集成 Spring Cloud 组件3、Spring Cloud Alibaba 功能服务注册与发现支持多协议…

教你如何搭建培训机构-学员管理系统,demo可分享

1、简介1.1、案例简介本文将介绍,如何搭建培训机构-学员管理。1.2、应用场景学员信息报表展示所有正式学员信息,可对学员进行分配班级、转课、续课、扩科、退课、阶段测评等操作。2、设置方法2.1、表单搭建1)新建表单【学员】,字段…

和日期相关的代码和bug——一道力扣题中的小发现

目录 Day of the Week 题目大意 常规方法 Python代码 Golang代码 C代码 基姆拉尔森公式 Python代码 Golang代码 C代码 使用库函数 Python代码 Golang代码 C代码 Day of the Week Given a date, return the corresponding day of the week for that date. The inp…

微信协议网页版微信协议解析

最近在做个微信机器人,所以研究了网页版的微信协议及相关接口,在这里简单总结一下。从表面上看,对于网页版微信我们的使用流程是这样的:很简单,只有四步,但如果细化到内里细节的话,上面这简单四…

华为OD机试真题 用 C++ 实现 - 服务依赖

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

ADC模数转换器(基于STM32F407)

简介 Analog-to-digital converters(模拟数字转换器),我的STM32F407中内置3个ADC,每个 ADC 有 12 位、10 位、8 位和 6 位可选,ADC 具有独立模式、双重模式和三重模式,对于不同 AD 转换要求几乎都有合适的…

mysql高级-day03

mysql高级-day03 集群: 主从模式(高可用 读写分离) 主主模式 主从级联 主主级联半同步模式(理解 表达出来)面试异步模式(理解 表达出来)面试搭建主从 搭建主主(docker)数据分片: 水平 垂直(数据库 表)面试策略有哪些(负载均衡策略)4种读写分离 主从切换 1 Mysql复制架构 1.1…

Linux 文件基本属性

Linux 系统是一种典型的多用户系统,不同的用户处于不同的地位,拥有不同的权限。 为了保护系统的安全性,Linux 系统对不同的用户访问同一文件(包括目录文件)的权限做了不同的规定。 在 Linux 中我们通常使用以下两个命…

JAVA虚拟机JVM之内存模型

内存模型 java 内存模型 很多人将【java 内存结构】与【java 内存模型】傻傻分不清,【java 内存模型】是 Java Memory Model(JMM)的意思。 关于它的权威解释,请参考 https://download.oracle.com/otn-pub/jcp/memory_model-1.0…