2020秋招面试JVM虚拟机高频问题总结 问题+答案(5)

简介: 2020秋招面试JVM虚拟机高频问题总结 问题+答案(5)

类加载器加载Class大致要经过如下8个步骤:

1、检测此Class是否载入过,即在缓冲区中是否有此Class,如果有直接进入第8步,否则进入第2步。

2、如果没有父类加载器,则要么Parent是根类加载器,要么本身就是根类加载器,则跳到第4步,如果父类加载器存在,则进入第3步。

3、请求使用父类加载器去载入目标类,如果载入成功则跳至第8步,否则接着执行第5步。

4、请求使用根类加载器去载入目标类,如果载入成功则跳至第8步,否则跳至第7步。

5、当前类加载器尝试寻找Class文件,如果找到则执行第6步,如果找不到则执行第7步。

6、从文件中载入Class,成功后跳至第8步。

7、抛出ClassNotFountException异常。

8、返回对应的java.lang.Class对象。


3.什么是双亲委派模型?


image.png


双亲委派模式是在Java 1.2后引入的,其工作原理的是,如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式,即每个儿子都很懒,每次有活就丢给父亲去干,直到父亲说这件事我也干不了时,儿子自己想办法去完成,这不就是传说中的实力坑爹啊?


4.双亲委派模型的工作过程以及使用它的好处。


采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。其次是考虑到安全因素,java核心api中定义类型不会被随意替换,假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。


六、OOM内存溢出的排查

什么是OOM

OOM为out of memory的简称,来源于java.lang.OutOfMemoryError,指程序需要的内存空间大于系统分配的内存空间,OOM后果就是程序crash;可以通俗理解:程序申请内存过大,虚拟机无法满足,然后自杀了。


导致OOM问题的原因

为什么会没有内存了呢?原因不外乎有两点:


1)分配的少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。


2)应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出。


内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用。


内存溢出:申请的内存超出了JVM能提供的内存大小,此时称之为溢出。


最常见的OOM情况有以下三种:


•java.lang.OutOfMemoryError: Java heap space ------>java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。

•java.lang.OutOfMemoryError: PermGen space 或 java.lang.OutOfMemoryError:MetaSpace ------>java方法区,(java8 元空间)溢出了,一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。

•java.lang.StackOverflowError ------> 不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。

排查手段

一般手段是:先通过内存映像工具对Dump出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏还是内存溢出。


•如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链。这样就能够找到泄漏的对象是通过怎么样的路径与GC Roots相关联的导致垃圾回收机制无法将其回收。掌握了泄漏对象的类信息和GC Roots引用链的信息,就可以比较准确地定位泄漏代码的位置。


•如果不存在泄漏,那么就是内存中的对象确实必须存活着,那么此时就需要通过虚拟机的堆参数( -Xmx和-Xms)来适当调大参数;从代码上检查是否存在某些对象存活时间过长、持有时间过长的情况,尝试减少运行时内存的消耗。


Java OOM问题如何排查


七、系统CPU飙高和GC频繁,如何排查?

系统运行缓慢的五种情况:

代码中某个位置读取数据量较大,导致系统内存耗尽,从而导致Full GC次数过多,系统缓慢;

代码中有比较耗CPU的操作,导致CPU过高,系统运行缓慢; 相对来说,这是出现频率最高的两种线上问题,而且它们会直接导致系统不可用。另外有几种情况也会导致某个功能运行缓慢,但是不至于导致系统不可用:

代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;

某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;

由于锁使用不当,导致多个线程进入死锁状态,从而导致系统整体比较缓慢。

系统缓慢的情况分析

通过 top命令查看CPU情况,如果CPU比较高,则通过top -Hp 命令查看当前进程的各个线程运行情况,找出CPU过高的线程之后,将其线程id转换为十六进制的表现形式,然后在jstack日志中查看该线程主要在进行的工作。这里又分为两种情况

如果是正常的用户线程,则通过该线程的堆栈信息查看其具体是在哪处用户代码处运行比较消耗CPU;

如果该线程是VM Thread,则通过jstat -gcutil 命令监控当前系统的GC状况,然后通过jmap dump:format=b,file= 导出系统当前的内存数据。导出之后将内存情况放到eclipse的mat工具中进行分析即可得出内存中主要是什么对象比较消耗内存,进而可以处理相关代码;

如果通过 top 命令看到CPU并不高,并且系统内存占用率也比较低。此时就可以考虑是否是由于另外三种情况导致的问题。具体的可以根据具体情况分析:

如果是接口调用比较耗时,并且是不定时出现,则可以通过压测的方式加大阻塞点出现的频率,从而通过jstack查看堆栈信息,找到阻塞点;

如果是某个功能突然出现停滞的状况,这种情况也无法复现,此时可以通过多次导出jstack日志的方式对比哪些用户线程是一直都处于等待状态,这些线程就是可能存在问题的线程;

如果通过jstack可以查看到死锁状态,则可以检查产生死锁的两个线程的具体阻塞点,从而处理相应的问题。

系统CPU飙高和GC频繁,如何排查?


CMS垃圾收集器

G1垃圾收集器

深入剖析JVM:G1收集器+回收流程+推荐用例


CMS垃圾收集器与G1垃圾收集器的区别

区别一: 使用范围不一样

CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用

G1收集器收集范围是老年代和新生代。不需要结合其他收集器使用


区别二: STW的时间

CMS收集器以最小的停顿时间为目标的收集器。


G1收集器可预测垃圾回收的停顿时间(建立可预测的停顿时间模型)


区别三: 垃圾碎片

CMS收集器是使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片


G1收集器使用的是“标记-整理”算法,进行了空间整合,降低了内存空间碎片。


G1回收器的特点

G1的出现就是为了替换jdk1.5种出现的CMS,这一点已经在jdk9的时候实现了,jdk9默认使用了G1回收器,移除了所有CMS相关的内容。G1和CMS相比,有几个特点:


控制回收垃圾的时间:这个是G1的优势,可以控制回收垃圾的时间,还可以建立停顿的时间模型,选择一组合适的Regions作为回收目标,达到实时收集的目的


空间整理:和CMS一样采用标记-清理的算法,但是G1不会产生空间碎片,这样就有效的使用了连续空间,不会导致连续空间不足提前造成GC的触发


G1把Java内存拆分成多等份,多个域(Region),逻辑上存在新生代和老年代的概念,但是没有严格区分


image.png


依旧存在新生代老年代的概念,但是没有严格区分。Region最多分为2048个


CMS与G1垃圾收集器的区别


参考链接

文末附一个关于JVM虚拟机的链接

https://blog.csdn.net/qq_41701956/article/details/81664921


面试官:谈谈你对JVM垃圾收集器的了解

https://www.jianshu.com/p/9eb474741692


GC详解及Minor GC和Full GC触发条件总结

https://blog.csdn.net/YHYR_YCY/article/details/52566105


JVM调优的常见命令行工具有哪些?

https://www.jianshu.com/p/e0f44d0147ea


深入理解虚拟机之类文件结构

https://yq.aliyun.com/articles/591525?utm_content=m_49522


深入理解虚拟机之虚拟机类加载机制

https://yq.aliyun.com/articles/591526?utm_content=m_49521#


双亲委派模式工作原理

https://www.cnblogs.com/mybatis/p/9396135.html


目录
相关文章
|
2月前
|
监控 算法 Java
Java虚拟机(JVM)的垃圾回收机制深度解析####
本文深入探讨了Java虚拟机(JVM)的垃圾回收机制,旨在揭示其背后的工作原理与优化策略。我们将从垃圾回收的基本概念入手,逐步剖析标记-清除、复制算法、标记-整理等主流垃圾回收算法的原理与实现细节。通过对比不同算法的优缺点及适用场景,为开发者提供优化Java应用性能与内存管理的实践指南。 ####
|
1月前
|
监控 算法 Java
Java虚拟机(JVM)垃圾回收机制深度剖析与优化策略####
本文作为一篇技术性文章,深入探讨了Java虚拟机(JVM)中垃圾回收的工作原理,详细分析了标记-清除、复制算法、标记-压缩及分代收集等主流垃圾回收算法的特点和适用场景。通过实际案例,展示了不同GC(Garbage Collector)算法在应用中的表现差异,并针对大型应用提出了一系列优化策略,包括选择合适的GC算法、调整堆内存大小、并行与并发GC调优等,旨在帮助开发者更好地理解和优化Java应用的性能。 ####
49 0
|
5天前
|
存储 监控 算法
Java JVM 面试题
Java JVM(虚拟机)相关基础面试题
|
2月前
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
1月前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
1月前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
2月前
|
机器学习/深度学习 监控 算法
Java虚拟机(JVM)的垃圾回收机制深度剖析####
本文深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法、性能调优策略及未来趋势。通过实例解析,为开发者提供优化Java应用性能的思路与方法。 ####
60 1
|
2月前
|
存储 算法 安全
JVM常见面试题(四):垃圾回收
堆区域划分,对象什么时候可以被垃圾器回收,如何定位垃圾——引用计数法、可达性分析算法,JVM垃圾回收算法——标记清除算法、标记整理算法、复制算法、分代回收算法;JVM垃圾回收器——串行、并行、CMS垃圾回收器、G1垃圾回收器;强引用、软引用、弱引用、虚引用
|
2月前
|
监控 Java 开发者
Java虚拟机(JVM)深度优化指南####
本文深入探讨了Java虚拟机(JVM)的工作原理及其性能优化策略,旨在帮助开发者通过理解JVM的内部机制来提升Java应用的运行效率。不同于传统的技术教程,本文采用案例分析与实战技巧相结合的方式,为读者揭示JVM调优的艺术。 ####
66 8
|
2月前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。