JVM面试
2021-10-18 09:42:28 0 举报
AI智能生成
登录查看完整内容
2021 年秋招常见 JVM 知识
作者其他创作
大纲/内容
1. 强引用:不回收2. 软引用:内存不足则回收3. 弱引用:发现即回收4. 虚引用:对象跟踪回收,无法通过虚引用获取对象
引用
1. 虚拟机栈中的对象2. static 修饰对象3. 本地方法栈中引用的对象4. final 修饰的对象
gc root
可达性分析
标记算法
1. 将内存分为两块,回收时,将eden 和 s0 区复制到 s1 中2. 清除eden 和 s0 区3. 将 s0 和 s1 互换
复制
1. 从GCRoot 进行搜索,标记存活对象2. 收集器从内存头到尾遍历,对未标记对象进行清理
标记清除
1. gc root 进行搜索,标记存活对象2. 将存活对象移动至内存的一端3. 清除掉边界外的对象
标记整理
回收算法
STW 暂停用户线程,单线程收集,只有一个回收线程,使用 复制 算法
serial
serial 的多线程版本,有多个回收线程,使用 复制 算法
parNew
吞吐量 = 运行代码时间 / (运行用户代码时间 + 垃圾收集时间)
吞吐量优先,多线程回收, 使用 复制 算法
Parallel Scavenge
年轻代收集器
serial的 老年代版本,使用 标记整理 算法
serial Old
Parallel 的老年代版本 采用 标记整理 算法
Parallel Old
暂停时间优先:单次 stw 时间最短
cms 是Hotspot虚拟机中第一款真正意义上的并发收集器,实现了垃圾收集线程与用户线程同时工作【使用 标记清除 算法】1. 初始标记:会stw 搜索 GcRoot 直接关联的对象2. 并发标记:递归遍历直接关联对象3. 重新标记:stw 重新标记在并发标记中产生的垃圾4. 并发清理:并发清理
CMS
老年代收集器
官方给g1设定的目标是 在延迟可控的情况下获得尽可能高的吞吐量G1 将内存分割为很多不相关的区域(region),使用不同region来代表 eden、s0\\s1、幸存者1区、老年代等;G1 避免在Java堆中进行全域垃圾收集,g1 跟踪各个 Region 里面的垃圾堆的价值大小在后台维护一个优先列表,每次根据允许时间,优先回收价值大的region
G1
整堆 收集器
垃圾收集器
在GC事件发生过程中,会停止其他用户线程可达性分析算法中枚举根节点(GC Roots)会导致所有Java执行线程停顿(分析过程中对象引用关系会导致结果的准确性无法保证)
stw
程序执行时并非所有地方都能停顿下来开始GC,只有特定位置可以停顿,这些位置就是 safe point;设置一个中断标志,各个线程运行到 safe point主动轮询这个标志,如果中断标志为真,则将当前线程中断挂起。
safe point
关键信息
垃圾收集
排查\\调优
负责加载 rt.jar 即 java javax sun 开头的类
引导类加载器
负责加载 jre/lib/ext 下的类
扩展类加载器
其他类的加载器
应用类加载器
1. 继承 ClassLoader2. 重写 findClass() 方法
自定义类加载器
类加载器
1. 将字节码静态存储结构转化成方法区运行时数据结构2. 在方法区生成这个类的
加载
保证被加载的类文件,满足Java 虚拟机规范
验证
为 static 修饰的变量分配内存,并赋初始值【0、null】
准备
符号引用&直接引用
将二进制数据中的符号引用转换为直接引用
解析
链接
本质上是 <clinit> 方法的执行,对 static 修饰的变量进行赋值
初始化
类加载过程
每个类都有对应的加载器,当一个类需要加载时,会向上进行委托,直到引导类加载器,如果类加载器不负责加载该类,则向下尝试加载好处是,保证了类只加载一次,且加载的是正确的类【破坏方式,写一个自定义的类加载器】
双亲委派机制
一块较小的空间,可以看做是当前线程锁执行的字节码行号指示器字节码解释器通过改变计数器的值选取下一条指令,程序分支、跳转循环、异常处理、线程切换恢复都需要通过计数器完成。没有OOM的区域
程序计数器
存储方法 参数、方法内变量,定义为一个数字数字,类型包括 基本数据类型、对象引用类型、返回地址类型单位是 槽 sloat,32位类型占1个、64位类型和引用类型占两个
局部变量表
在方法执行过程中,根据字节码指令,进行入栈\\出栈的操作主要用于保存计算过程的中间结果,同时作为计算过程中变量的临时存储空间
操作数栈
指向运行时常量池的方法引用,例如一个方法调用了其他方法,就是通过常量池中指向方法的符号引用表示的,动态链接的作用是将符号引用转换成调用方法的直接引用
动态链接
方法返回地址
单位是栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息每个方法从调用到执行完成,对应一个栈帧在虚拟机中入栈到出栈的过程
Java虚拟机栈
本地方法:有时我们编写的程序需要 操作系统、底层硬件的支持本地方法接口为我们屏蔽了这些的底层实现
与Java 虚拟机栈类似,区别在于用于执行 native 方法
本地方法栈
线程私有
Thread Local Allocation Buffer 由于对象实例创建在JVM 中非常频繁,因此在并发环境下从堆区划分内存空间是不安全的,从内存模型的角度,对 Eden 进行细分,JVM 为每个线程分配了一个私有缓存区域。虽然不是所有对象实例都能在TLAB中成功分配,但JVM会将TLAB作为内存分配的首选,开发人员可以通过 -XX:useTLAB 设置是否开启。
TLAB
由于对象往往是 “朝生夕死的”,根据对象的特点,JVM 将 堆空间分成了两部分,年轻代、老年代,年轻代发生gc的次数较为频繁,而老年代则较少的发生gc,年轻代根据所选用的 垃圾收集算法 ,分割成了 eden 区 s0 和 s1 区。
分代
堆
【Hotspot】JDK 7 之前方法区被称为永久代,存放于Java 内存上JDK 8 称为 元空间,存放于 直接内存
方法区
线程公有
运行时数据区
JVM面试
0 条评论
回复 删除
下一页