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

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

20200723092220992.png

一、JVM【JDK8】


1.1 JVM结构图


20200723091401671.png


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初始默认值


20200723092942527.png

1.5 JVM常用调优参数


20200723170525636.png



-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];


20200724092540565.png

GC类型:

20200724092628736.png


FullGC:


20200724093050268.png

-XX:SurvivorRatio


20200724095606560.png

-XX:NewRatio

20200724100844115.png

-XX:MaxTenuringThreshold 设置垃圾回收的最大年龄

20200724103250931.png


二、强、软、弱、虚引用

20200724104231603.png



2.1 强引用Reference


当内存不足的时候,对于强引用对象,就算是出现OOM也不会对该对象进行回收。把一个对象赋值给一个引用变量,这个变量就是一个强引用。该对象的以后永远不会被JVM回收,经常造成内存泄漏OOM。

如果没有引用才可以被回收。


20200724105330523.png

2.2 软引用SoftReference


当内存足够不回收,不够就要回收,尽量不要OOM。

20200724105846700.png


结果:一个null 一个 有值

当内存不够用时候呢?

配置小内存,大对象试试

20200724110128533.png


结果:就发生了OOM,后面两个输出均为null


2.3 弱引用WeakReference


只要有弱引用就会回收,不管内存够不够用。


java.lang.ref.WeakReference


20200724110659263.png


结果:后两个全为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


20200725095305328.png


【养老区】:

无法整理空间 碎片

4.G1

将堆内存分割成不同的区域然后并发的随其进行垃圾回收

JVM参数:-XX:+UseG1GC

横跨young old


20200725100543537.png


面向服务器的收集器

更高的并发

更少的延迟

整理空间更快

不需要很大的堆内存

不会产生很多内存碎片

用户可以指定停顿时间

目标为取代CMS

jdk7中有G1,jdk9中变成默认的垃圾回收器来替代CMS

总结:

20200725100008405.png

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


20200724162147111.png


20200725085248855.png


3.4 JVM的Server/Client模式


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


3.5 JVM GC+Springboot部署调参


启动流程


springboot工程

maven clean

maven package

微服务启动,同时配置JVM GC的调优参数【内,外】

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

20200725104616815.png


// 所有的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


目录
相关文章
|
27天前
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
18天前
|
存储 算法 安全
JVM常见面试题(四):垃圾回收
堆区域划分,对象什么时候可以被垃圾器回收,如何定位垃圾——引用计数法、可达性分析算法,JVM垃圾回收算法——标记清除算法、标记整理算法、复制算法、分代回收算法;JVM垃圾回收器——串行、并行、CMS垃圾回收器、G1垃圾回收器;强引用、软引用、弱引用、虚引用
|
27天前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
2月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
73 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
2月前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
1月前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
2月前
|
Java 应用服务中间件 程序员
JVM知识体系学习八:OOM的案例(承接上篇博文,可以作为面试中的案例)
这篇文章通过多个案例深入探讨了Java虚拟机(JVM)中的内存溢出问题,涵盖了堆内存、方法区、直接内存和栈内存溢出的原因、诊断方法和解决方案,并讨论了不同JDK版本垃圾回收器的变化。
33 4
|
2月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
59 3
|
2月前
|
Java API 对象存储
JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?
本文详细解析了JVM类加载过程的关键步骤,包括加载验证、准备、解析和初始化等阶段,并介绍了元数据区、程序计数器、虚拟机栈、堆内存及本地方法栈的作用。通过本文,读者可以深入了解JVM的工作原理,理解类加载器的类型及其机制,并掌握类加载过程中各阶段的具体操作。
|
2月前
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?