JVM可以说是面试必问内容之一,其中两个大头:类加载器和垃圾回收,今天就讲一讲这两大巨头,希望对诸位有帮助。
类加载器
首先看下他的基础结构
在面试过程中,会着重问你一个类是如何加载的,以及双亲委派模型。如图,最重要的三个类加载器:(以下使用简称)BSClassLoader ExtClassLoader AppClassLoader。
面试时,我们无需关心他们具体负责哪一块区域,有兴趣的朋友可以自行深入探讨,以下只讨论双亲委派模型。
应该怎么回答呢
首先,jvm自带三个类加载器,分别是:BSClassLoader ExtClassLoader AppClassLoader
提到类加载器就不得不提到双亲委派模型:当需要加载一个类时,会从App进来然后向上请求Ext,Ext继续向上请求BS加载,如果BS能加载就由BS加载,不能则由Ext,还不能就由App加载。
虽然名字是叫“双亲”委派模型,但是这三个加载器并不是继承关系。从源码可知,他们其实是组合关系。至于为何是叫做“双亲”,我推测可能是内部代码用到了Parent的关键字(纯个人推测)。
为何要使用双亲委派模型
垃圾回收
垃圾回收可以说也是大头中的大头,但其实了解后也不算难,首先我们来看看JVM内存空间和一个java文件加载的过程(这张图很重要!一定需要背下来的)
一般gc发生在heap(图中黄色的堆区),堆区内部组成如下:
左边Eden区加两个幸存区(survivor)为新生代,占1/3,右边为老年代,占2/3。
当一个对象进来后会从新生代经历一次次gc(经历了但不一定回收!),如果经历了15次(默认)垃圾回收还活下来了,则会放入老年代。
垃圾回收算法(面试必问)
1、标记清除法
很简单,标记出需要回收的对象,然后清除。原理很简单,但是有一个致命缺陷,因为垃圾和需要保留下来的是随机分配的,清理完后会造成大量的内存碎片,是我们不想看到的情况。
2、复制算法(主要在新生代)
先复制一份同样大小的内存空间,当发生gc时,就把需要的内容存入新内存中,然后直接舍弃掉旧内存,这样就解决了内存碎片的问题。但是也有缺陷:需要占用更大的内存空间。
3、标记压缩算法(老年代)
同样是先标记,但是他会将标记出来有用的对象压缩到内存的同一侧,然后一刀切除尾端那些剩余的垃圾和空白内存,这样同样能解决内存碎片这个问题。
简单介绍一下面试百分百会提到的专有名词(同样超级重要!):
gc(垃圾回收):回收一个垃圾(对,就是这么简单的解释)。
STW(Stop The World):指进行GC一个线程,准备GC。
full gc:这个词官方并没有给出明确概念,但其确实是相当重要的概念。结合多位大佬的经验可以简单翻译一下:“满,全”gc,大约就是当达成一定条件后就会进行一次full gc,对堆内的老年代进行一次大清洗。条件如下(只列出最重要的两点)
1、System.gc();这条指令需要记住,尤其重要,一但运行一次就会进行full gc。
2、OutofmemoryException:也好理解,当内存爆满时候,肯定会进行一次full gc来清理。
这个异常一般发生在老年代,所以一般是老年代内存不足。
最重要的知识点已经提炼出来,其实内部具体还有非常多的细节需要处理,本文只是讲解了真实遇到的面试题。各位在闲暇之余可以观看此文,以此提高对jvm的记忆