JVM的问与答
真实模拟面试官和"我"的问与答,可能我的回答不是特别官方的回答,甚至有的会带有一些口语化,而且这边没有图片去做解释一些原理(毕竟不是学习笔记)
Q:你知道类加载机制是什么吗?
A:首先类加载机制整个过程包含了如下的几个部分:装载,链接,初始化,应用,卸载
-
装载
这个过程简单的来说,是将.class的字节码文件,编译成字节流,再通过类加载器加载到内存中的一个过程,将静态的数据结构,转到运行数据区
-
链接
-
验证
-
准备
- 将一些静态变量赋默认值,开辟空间
-
解析
- 将符号引用变为直接引用
-
-
初始化
- 初始化这个类
使用: 就是我们用的最多的
卸载:这个在属于回收部分
Q:你了解类加载器吗?
A:嗯,我知道,类加载器主要包括四个,从上往下,依次是Bootstrap类加载器,Extension加载器,Application 加载器,Custom自定义类加载器。我知道在整个类加载的过程中,是从下往上找,然后加载的时候是从上往下,然后由于全盘负责的机制,会优先当前的类加载器。其实从下往上找,到加载从上往下用父类区做加载,这个就是我们常说的父类委托,也叫双亲委派。
如果想要打破双亲委派,我知道的两个方法,一个可以重写底层的类加载的寻找类加载器的方法,或者SPI,通过线程上下文的类加载器
Q:整个jvm的数据存储结构,大概是什么样子的?
A: 这个就要说说运行数据区了,主要分为方法区(也叫非堆),堆,虚拟机栈,本地方法栈,程序计数器。这里的虚拟机栈,本地方法栈,程序计数器是属于线程私有的,如果该线程结束以后,自然会被销毁。这里重点说说共享的堆和方法区。
系统中的方法区一般会有这个类的属性,静态方法,静态变量等信息
堆的会一般会放你在项目中实例化的数据,其中对象中的方法使用会压到虚拟机栈中,其中的压进去的栈帧有几个部分构成:局部变量,操作数栈,动态链接,方法的返回地址等信息。
Q:你上述说的堆,我们都知道是分代设计的,你知道为什么?
A:因为我们在项目中的对象大多数的生命周期都不长,如果说全放在一个堆的时候,到时候做垃圾回收的时候,寻找所有的垃圾对象的时间会过长,停顿的时间就会过长,对业务不太友好。所以要为不同的对象分配出不同的区间,分类进行回收。一般分为老年代和新生代,新生代又分为eden和survior.其中在gc收集器总新生代一般采用复制算法。至于在新生代为什么会有2个区呢?我认为主要是为了缓冲,不让一些对象因为内存碎片直接进入老年区。
Q:你刚提到复制算法,那你还知道哪些垃圾回收算法?
A: 现在的垃圾回收器大多数使用的是可达性分析算法来判断这个对象是否为可达对象(即有用的对象)让其作为标记,不可达的作为垃圾,由此可以有算法
1.标记清除算法(会产生内存碎片)
2.标记整理算法
随机整理
顺序整理
滑动整理
双指针算法
单次循环
lisp2算法(3个):
- 分代收集算法: 卡表,稀疏表,细粒度,粗粒度
然后在清除整理的时候,再分配的时候一般会有三种分配方式,首次适应,最佳适应,最差适应
Q:你知道哪些常见的垃圾收集器,简单谈谈
A: CMS,Serial, ParNew,Parallel Scavenge,G1,ZGC
CMS: 主要在老年代用的是标记清除算法,为了减少停顿时间