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