写点什么

JVM 超神之路:金三银四跳槽需要的 JVM 知识点,都给你整理好了

作者:Java你猿哥
  • 2023-03-24
    湖南
  • 本文字数:3463 字

    阅读完需:约 11 分钟

JVM超神之路:金三银四跳槽需要的JVM知识点,都给你整理好了

一、ClassLoader 类加载器

1、类加载过程

2、类加载器种类以及加载范围

3、双亲委派是什么

4、为啥要有双亲委派

5、为什么需要破坏双亲委派模型

6、如何破坏双亲委派模型

7、如何自定义一个类加载器

8、热部署原理

9、常见笔试题

二、Java 内存区域

1、Java 内存结构

2、对象创建时堆内存分配算法

3、对象在内存中的存储布局

4、对象怎么定位

5、判断对象是否能被回收的算法

6、如何判断对象是否能被回收

7、Java 堆内存组成部分

8、什么时候抛出 StackOverflowError

9、Java 中会存在内存泄漏吗,请简单描述。

10、栈帧是什么?包含哪些东西

11、简述一个方法的执行流程

12、方法区会被回收吗

13、一个对象包含多少个字节

14、为什么把堆栈分成两个

15、栈的起始点是哪

16、为什么基本类型不放在堆里

17、Java 参数传递是值传递还是引用传递

18、为什么不推荐递归

19、为什么参数大于 2 个要放到对象里

20、常见笔试题

三、GC 垃圾回收

1、GC 是什么?为什么要 GC

2、你能保证 GC 执行吗?

3、对象的引用类型有哪几种,分别介绍下

4、垃圾收集算法有哪些

5、为什么要分代

6、分代垃圾回收是怎么工作的

7、垃圾回收器有哪些

8、详细介绍一下 CMS 垃圾回收器?

9、详细介绍一下 G1 垃圾回收器?

10、GC 日志分析

11、Minor GC 与 Full GC 分别在什么时候发生

12、新生代垃圾回收器和老年代垃圾回收器都有哪些?有什么区别?

13、栈上分配是什么意思

14、简述下对象的分配规则

四、实战调优

1、你在项目中都使用了哪些参数打印 GC?

2、常用的调优工具有哪些?

3、如果有一个系统,内存一直消耗不超过 10%,但是观察 GC 日志,发现 FGC 总是频繁产生,会是什么引起的?

4、线上一个系统跑一段时间就栈溢出了,怎么办 ?

5、系统 CPU 经常 100%,如何调优?

6、系统内存飙高,如何查找问题?

7、大型项目如何进行性能瓶颈调优

8、你实际遇到调优的场景

GC 常用参数

Parallel 常用参数

CMS 常用参数

G1 常用参数


四、实战调优

1、你在项目中都使用了哪些参数打印 GC?

具体的参数名称记不清楚了,但是我一般在项目中输出详细的 GC 日志,并加上可读性强的 GC 日志的时间戳。特别情况下我还会追加一些反映对象晋升情况和堆详细信息的日志,这些会单独打到 gc.log 文件中用来排查问题。另外,OOM 时自动 Dump 堆栈,我一般也会进行配置。

2、常用的调优工具有哪些?

JDK 内置的命令行:jps(查看 jvm 进程信息)、jstat(监视 jvm 运行状态的,比如 gc 情况、jvm 内存情况、类加载情况等)、jinfo(查看 jvm 参数的,也可动态调整)、jmap(生成 dump 文件的,在 dump 的时候会影响线上服务)、jhat(分析 dump 的,但是一般都将 dump 导出放到 mat 上分析)、jstack(查看线程的)。

JDK 内置的可视化界面:JConsole、VisualVM,这两个在 QA 环境压测的时候很有用。

阿里巴巴开源的 arthas:神器,线上调优很方便,安装和显示效果都很友好。

3、如果有一个系统,内存一直消耗不超过 10%,但是观察 GC 日志,发现 FGC 总是频繁产生,会是什么引起的?

检查下系统是否存在 System.gc() ;

4、线上一个系统跑一段时间就栈溢出了,怎么办 ?

1.首先检查下是否有死归这种无限递归的程序或者递归方法太多

2.可以看下栈大小,若太小则可以指定-Xss 参数设置栈大小

5、系统 CPU 经常 100%,如何调优?

CPU100%,那肯定是有线程一直在占用着系统资源,所以具体方法如下:

  1. 找出哪个进程 cpu 占用高(top 命令)

  2. 该进程中的哪个线程 cpu 占用高(top -Hp $pid 命令)

  3. 将十进制的 tid 转化为十六进制(printf %x $tid 命令)

  4. 导出该线程的堆栈 (jstack $pid >$pid.log 命令)

  5. 查找哪个方法(栈帧)消耗时间 (less $pid.log)

  6. 可以确认工作线程占比高还是垃圾回收线程占比高

  7. 修改代码

6、系统内存飙高,如何查找问题?

  1. 找出哪个进程内存占用高(top 命令)

  2. 查看 jvm 进程号(jps 命令)

  3. 导出堆内存 (jmap 命令生成 dump 文件,注意:线上系统,内存特别大,jmap 执行期间会对进程产生很大影响,甚至卡顿,所以操作前最好先从负载均衡里摘掉。)

  4. 分析 dump 文件 (比如 mat 软件)

7、大型项目如何进行性能瓶颈调优

1.数据库与 SQL 优化:一般 dba 负责数据库优化,比如集群主从等。研发负责 SQL 优化,比如索引、分库分表等。

2.集群优化:一般 OP 负责,让整个集群可以很容易的水平扩容,再比如 tomcat/nginx 的一些配置优化等。

3.硬件升级:选择最合适的硬件,充分利用资源。

4.代码优化:很多细节,可以参照阿里巴巴规范手册和安装 sonar 插件这种检测代码质量的工具。也可以适当的运用并行,比如 CountDownLatch 等工具。

5.jvm 优化:内存区域大小设置、对象年龄达到次数晋升老年代参数的调整、选择合适的垃圾收集器以及合适的垃圾收集器参数、打印详细的 GC 日志和 oom 的时候自动生成 dump。

6.操作系统优化

8、你实际遇到调优的场景

我们之前都是采取 zipkin 做分布式链路追踪,后来换成了 skywalking,所以将 zipkin 相关配置和代码都移除了,但是忘记移除 maven 坐标了,运行一段时间后导致了频繁 full gc ,最后 oom 了。

因为配置了 oom 后自动生成 dump 文件,所以分析 dump 文件发现大对象是 zipkin 包里的 ConcurrentHashMap$Node,通过观察 zipkin 的自动配置类 ZipkinAutoConfiguration 发现即使没有任何 zipkin 的配置,只要有 zipkin 的依赖都会创建一个异步报告者,默认的采样率是 10%,所以即使不配置相关配置项,也会以默认采样率 10%,发送到 zipkin,这是默认的地址是 http://localhost:9411/,此时发送到 localhost:9411 显然会连接拒绝。导致度量中的异常实例堆积,从而 OOM。

private float probability = 0.1f;
@ConfigurationProperties("spring.zipkin")public class ZipkinProperties {    private String baseUrl = "http://localhost:9411/";}
复制代码

附录

GC 常用参数

  • -Xmn:年轻代

  • -Xms:最小堆

  • -Xmx :最大堆

  • -Xss:栈空间

  • -XX:+UseTLAB:使用 TLAB,默认打开

  • -XX:+PrintTLAB:打印 TLAB 的使用情况

  • -XX:TLABSize:设置 TLAB 大小

  • -XX:+DisableExplictGC:禁用 System.gc()不管用 ,防止 FGC

  • -XX:+PrintGC:打印 GC 日志

  • -XX:+PrintGCDetails:打印 GC 详细日志信息

  • -XX:+PrintHeapAtGC:打印 GC 前后的详细堆栈信息

  • -XX:+PrintGCTimeStamps:打印时间戳

  • -XX:+PrintGCApplicationConcurrentTime:打印应用程序时间

  • -XX:+PrintGCApplicationStoppedTime:打印暂停时长

  • -XX:+PrintReferenceGC:记录回收了多少种不同引用类型的引用

  • -verbose:class:类加载详细过程

  • -XX:+PrintVMOptions:jvm 参数

  • -XX:+PrintFlagsFinal:-XX:+PrintFlagsInitial 必须会用

  • -Xloggc:opt/log/gc.log:gc 日志的路径以及文件名称

  • -XX:MaxTenuringThreshold:升代年龄,最大值 15

Parallel 常用参数

  • -XX:SurvivorRatio:年轻代中 eden 和 from/to 的比值。比如设置 3 就是 eden:survivor=3:2,也就是 from 和 to 各占 1,eden 占用 3

  • -XX:PreTenureSizeThreshold:大对象到底多大

  • -XX:MaxTenuringThreshold:升代年龄,最大值 15

  • -XX:+ParallelGCThreads:并行收集器的线程数,同样适用于 CMS,一般设为和 CPU 核数相同

  • -XX:+UseAdaptiveSizePolicy:自动选择各区大小比例

CMS 常用参数

  • -XX:+UseConcMarkSweepGC:设置年老代为并发收集

  • -XX:ParallelCMSThreads:CMS 线程数量

  • -XX:CMSInitiatingOccupancyFraction:使用多少比例的老年代后开始 CMS 收集,默认是 68%(近似值),如果频繁发生 SerialOld 卡顿,应该调小,(频繁 CMS 回收)

  • -XX:+UseCMSCompactAtFullCollection:在 FGC 时进行压缩

  • -XX:CMSFullGCsBeforeCompaction:多少次 FGC 之后进行压缩

  • -XX:+CMSClassUnloadingEnabled:年老代启用 CMS,但默认是不会回收永久代(Perm)的。此处对 Perm 区启用类回收,防止 Perm 区内存满。

  • -XX:CMSInitiatingPermOccupancyFraction:达到什么比例时进行 Perm 回收

  • GCTimeRatio:设置 GC 时间占用程序运行时间的百分比

  • -XX:MaxGCPauseMillis:停顿时间,是一个建议时间,GC 会尝试用各种手段达到这个时间,比如减小年轻代

G1 常用参数

  • -XX:+UseG1GC:开启 G1

  • -XX:MaxGCPauseMillis:建议值,G1 会尝试调整 Young 区的块数来达到这个值

  • -XX:GCPauseIntervalMillis:GC 的间隔时间

  • -XX:+G1HeapRegionSize:分区大小,建议逐渐增大该值,1 2 4 8 16 32。随着 size 增加,垃圾的存活时间更长,GC 间隔更长,但每次 GC 的时间也会更长 ZGC 做了改进(动态区块大小)

  • G1NewSizePercent:新生代最小比例,默认为 5%

  • G1MaxNewSizePercent:新生代最大比例,默认为 60%

  • GCTimeRatio:GC 时间建议比例,G1 会根据这个值调整堆空间

  • ConcGCThreads:线程数量

  • InitiatingHeapOccupancyPercent:启动 G1 的堆空间占用比例

文末:


2023 最新完整面试题及答案(都整理成文档),有很多干货,包含 mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等, 需要获取这些内容的朋友私信我: Java 即可。

用户头像

Java你猿哥

关注

一只在编程路上渐行渐远的程序猿 2023-03-09 加入

关注我,了解更多Java、架构、Spring等知识

评论

发布
暂无评论
JVM超神之路:金三银四跳槽需要的JVM知识点,都给你整理好了_Java_Java你猿哥_InfoQ写作社区