2020大厂面试之【JVM+GC】必考面试题讲解

在这里插入图片描述

一、JVM【JDK8】

1.1 JVM结构图

在这里插入图片描述

1.2 GC Roots的理解

思路就是通过一系列名字为“”GC Roots“”的对象作为哦起点,开始向下搜索,如果一个对象到GC Roots没有任何引用链连接时候,则说名对象不可用。也即给他一个集合的引用作为跟出发,通过引用关系遍历对象图,能被遍历到的对象被判断为存活,没有的话就是死亡。
在这里插入图片描述
可以作为GC Roots的对象

虚拟机栈中的对象
方法区中的类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中Native引用的对象

1.3 JVM调优的标配参数和X,XX参数

标配参数:
java -version
java -help

X参数:【了解】
-Xint: 解释执行
-Xcomp: 第一次使用编译成本地代码
-Xmixed:混合模式【默认的】

XX参数:
Boolean类型
-XX:+或者-某个属性值,+代表开启,-代表关闭
如何查看是否开启了某个参数

jps -l
jinfo -flag PrintGCDetails 4526
// 结果如下:
-XX:+PrintGCDetails 
表示激活了打印GC信息

KV设置类型
-XX:属性key=属性值value
如何设置元空间的大小???

jps -l
jinfo -flag MetaspaceSize 6350
// 默认21M
-XX:MetaspaceSize=21807104
// 程序运行调成1G
-XX:MetaspaceSize=1024m

jinfo举例

-Xms: -XX:InitialHeapSize
-Xmx:-XX:MaxHeapSize

1.4 JVM初始默认值

在这里插入图片描述

1.5 JVM常用调优参数

在这里插入图片描述
-Xms: -XX:InitialHeapSize 初始堆内存【存储空间】
-Xmx:-XX:MaxHeapSize 最大堆内存
-Xss:-XX:ThreadStackSize 设置单个线程栈空间的大小,一般默认为512k-1024k【运行空间】
一般0为出事的默认值
**-Xmn:**设置年轻代的大小
-XX:MetaspaceSize 设置元空间的大小,元空间不在虚拟机中,而是使用的是本地内存,仅受本地内存的限制。默认使用了20m左右
-XX:+PrintGCDetails 打印垃圾回收的细节情况

// 模拟产生OOM的情况下,查看垃圾回收的细节
JVM配置 -Xms:10m -Xmx:10m -XX:+PrintGCDetails 
程序设置50M大小的对象
byte[] byteArray = new byte[50 * 1024 * 1024];

在这里插入图片描述
GC类型:
在这里插入图片描述
FullGC:
在这里插入图片描述
-XX:SurvivorRatio
在这里插入图片描述
-XX:NewRatio
在这里插入图片描述
-XX:MaxTenuringThreshold 设置垃圾回收的最大年龄
在这里插入图片描述

二、强、软、弱、虚引用

在这里插入图片描述

2.1 强引用Reference

当内存不足的时候,对于强引用对象,就算是出现OOM也不会对该对象进行回收。把一个对象赋值给一个引用变量,这个变量就是一个强引用。该对象的以后永远不会被JVM回收,经常造成内存泄漏OOM。
如果没有引用才可以被回收。
在这里插入图片描述
在这里插入图片描述

2.2 软引用SoftReference

当内存足够不回收,不够就要回收,尽量不要OOM。
在这里插入图片描述
结果:一个null 一个 有值
当内存不够用时候呢?
配置小内存,大对象试试
在这里插入图片描述
结果:就发生了OOM,后面两个输出均为null

2.3 弱引用WeakReference

只要有弱引用就会回收,不管内存够不够用。
java.lang.ref.WeakReference
在这里插入图片描述
结果:后两个全为null

2.4 虚引用PhantomReference

形同虚设,与其他引用均不同,并不会决定对象的生命周期。
必须与引用队列联合使用ReferenceQueue
跟踪回收的状态。

三、GC垃圾回收

3.1 垃圾回收算法

1.引用计数
2.复制:内存开销
3.标记清除 :内存碎片
4.标记清除整理

3.2 垃圾回收器

这是垃圾回收算法的实现
1.Serial 串行垃圾回收器
他为单线程环境设计的只是用一个线程进行垃圾回收,会停止所有的用户线程

  • JVM参数:-XX:+UseSerialGC
  • 开启后默认在Serial(Young区用) + Serial Old(Old区用)的收集器组合
  • 新生代和老年代都会使用串行收集回收器,新生代使用复制算法,老年代使用标记-整理算法
    2.Parallel 并行垃圾回收器
    多个垃圾回收线程,用户线程暂停,适合于科学计算,大数据等弱交互场景。
  • 就是串行回收器的并行版本
  • JVM参数:-XX:+UserParNewGC
  • ParNew(Young区用) + Serial Old的组合,新生代使用赋值算法,老年代使用标机-整理算法
    3.CMS 并发标记清除垃圾回收器
    用户线程和垃圾回收线程,不一定并行或者交替,适合于高并发场景。
    JVM参数:-XX:UseConcMarkSweepGC
    在这里插入图片描述
    【养老区】:
    无法整理空间 碎片
    4.G1
  • 将堆内存分割成不同的区域然后并发的随其进行垃圾回收
  • JVM参数:-XX:+UseG1GC
  • 横跨young old
    在这里插入图片描述
  • 面向服务器的收集器
  • 更高的并发
  • 更少的延迟
  • 整理空间更快
  • 不需要很大的堆内存
  • 不会产生很多内存碎片
  • 用户可以指定停顿时间
  • 目标为取代CMS
  • jdk7中有G1,jdk9中变成默认的垃圾回收器来替代CMS
    总结:
    在这里插入图片描述

1: G1能充分利用多CPU、 多核环境硬件优势,尽量缩短STW。
2:G1整体上采用标记-整理算法,局部是通过复制算法,不会产生内存碎片。
3:宏观上看G1之中不再区分年轻代和老年代。把内存划分成多个独立的子区域(Region),可以近似理解为一个围棋的棋盘。
4:G1收集器里面讲整个的内存区都混合在一-起了 ,但其本身依然在小范围内要进行年轻代和老年代的区分,保留了新生代和老年代,但它们不再是物理隔离的,而是一部分Region的集合且不需要Region是连续的,也就是说依然会采用不同的GC方式来处理不同的区域。
5: G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制 准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换;

3.3 如何查看默认的垃圾回收器?

最后一个参数就是垃圾回收器的种类

java -XX:+PrintCommandLineFlags -version

在这里插入图片描述
在这里插入图片描述

3.4 JVM的Server/Client模式

  • 32位windows 默认是Client的JVM模式
  • 其他操作系统2G内存,2cpu以上的用Server模式
  • 64位 仅仅Server

3.5 JVM GC+Springboot部署调参

启动流程

  1. springboot工程
  2. maven clean
  3. maven package
  4. 微服务启动,同时配置JVM GC的调优参数【内,外】
  5. java -jar springbootxxxxx.war/jar

调参公式:

java -server JVM参数  -jar springbootxxxxx.war/jar

示例如下

// 1.参数调优
java -server -Xms1024m  -Xmx1024m  -XX:+UseG1GC -jar springbootxxxxx.war/jar

// 2.查看进程ID
jps -l 

// 3.查看信息
jinfo -flags 9969

四、Linux生产服务器变慢如何诊断?

操作步骤:

4.1 整机:top

或者 uptime 也可以
load average: 1.52, 0.98, 0.55
计算负载高: (1.52+0.98+0.55)/3 * 100% > 60%

4.2 CPU: vmstat

// 每2秒采样一次 一共采样3次
vmstat -n 2 3

在这里插入图片描述

// 所有的CPU  idle空闲虑
mpstat -P ALL 2

// 详细信息
pidstat -u l -p 5103

4.3 内存:free

// 内存 MB单位
free -m

// 查看额外 采样次数2S
pidstat -p 5103 -r 2

4.4 硬盘:df

// 简单方便 GB
df -h

4.5 磁盘IO: iostat

iostat -xdk 2 3

// 磁盘块设备分布
rkB/s每秒读取数据量kB;
wkB/s每秒写入数据量kB:
svctm /O0请求的平均服务时间,单位毫秒:
await l/O请求的平均等待时间,单位毫秒;值越小,性能越好:
util 一秒中有百分几的时间用于/O操作。接近100%时,表示磁盘带宽跑满,需要优化程序或者增加磁盘;
rkB/s、wkB/s根据 系统应用不同会有不同的值,但有规律遵循:长期、超大数据读写,肯定不正常,需要优化程序读取。
svctm的值与await的值很接近,表示几乎没有I/O等待,磁盘性能好,
如果await的值远高于svctm的值,则表示1/O队列等待 太长,需要优化程序或更换更快磁

// 具体信息
pidstat -d 2 -p 5103

4.6 网络IO:ifstat

// 采样频率1S
ifstat 1

猜你喜欢

转载自blog.csdn.net/wyn_365/article/details/107528728
今日推荐