本人今年参加了很多面试,也有幸拿到了一些大厂的offer,整理了众多面试资料,后续还会分享众多面试资料,感兴趣的朋友可收藏+关注,
现分享如下:
文章目录
- 1. Java虚拟机运行时数据区
- 2. Java堆
- 3. 垃圾回收
- 3.1 如何确定对象能否被销毁
- 3.2 垃圾回收算法
1. Java虚拟机运行时数据区
(1)堆
栈管运行,堆管存储;虚拟机栈负责执行代码,而堆则负责存储数据。
Java堆具有以下几个特点:
· 存储我们new出来的对象,不存放基本类型和对象引用
· 由于创建了大量对象,垃圾回收器主要工作在这块区域
· 线程共享区域,因此是线程不安全的
· 能够发生OutOfMemoryError
另外,堆区还可以划分新生代和老年代,新生代又可以进一步划分为Eden区,Surviveor1区,Survivor2区。
(2)方法区
方法区也是一块被重点关注的区域,主要特点如下:
· 线程共享区域
· 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
· 当方法无法满足内存分配需求时,将会排除OutOfMemoryError.
(3)虚拟机栈
· 虚拟机栈是线程私有的,每一个线程独享一个虚拟机栈,它的生命周期与线程相同
· 虚拟机栈存放的是基本数据类型(boolean、byte、char、short、float、long、double)以及对象的引用类型(reference类型,它不同于对象本身,根据不同的虚拟机实现,他可能是一个指向对象起始地址的应用指针,也可能是一个指向代表对象的句柄等)和returnAddress类型(指向了一条字节码指令的地址)
· 这个区域可能有两种异常:如果线程请求的深度大于虚拟机所允许的深度,将抛出StackOverflowError;如果虚拟机栈可以动态扩,当扩展时无法申请到足够内存时将抛出OutOfMemoryError.
(4)本地方法栈
本地方法栈与虚拟机栈所发挥的作用非常相似,其区别不过是虚拟机栈为虚拟机执行
Java方法(也就是字节码)服务,而本地方法则是为虚拟机使用到的Native方法服务。
(5)程序技术器
线程私有,它的作用是记录当前线程所执行的位置,这样,当线程重新获得CPU的执行权的时候,就直接从记录的位置开始执行,分支、跳转、循环、异常处理也都依赖这个程序计数器来完成。
2. Java堆
Java堆可以划分为新生代和老年代,新生代又可以进一步划分为Eden区、Survivor1区、Survivor2区。具体比例如下:
3. 垃圾回收
3.1 如何确定对象能否被销毁
通常判断一个对象是否被销毁有两种方法:
(1)引用计数法: 为对象添加一个引用计数器,每当一个对象被引用,则+1;每当一个对象引用失效时,则-1.当计数器为0时,表示该对象没有被引用,可以被回收
(2)可达性分析法: 通过一系列被称之为GC root,沿着引用链进行搜索,凡是在引用链的对象都不会被回收;反之,则可以被回收。
就像上图的那样,绿色部分的对象都在GC Roots的引用链上,就不会被垃圾回收器回收,灰色部分的对象没有在引用链上,自然就被判定为可回收对象。可作为GCroots的对象有:
· 虚拟机栈(栈桢中的本地变量表)中的引用的对象
· 方法区中的类静态属性引用的对象
· 方法区中的常量引用的对象
· 本地方法栈中JNI(Native方法)引用的对象
3.2 垃圾回收算法
(1)标记-清除算法
分为两个阶段:标记阶段和清除阶段。
标记阶段:首先通过根节点,标记所有从根节点开始的对象,未被标记的对象就是未被引用的垃圾对象。清除阶段:清除所有未被标记的对象
缺点:
1) 容易产生内存碎片,再来一个比较大的对象时不够分配时,会提前触发垃圾回收。
2) 扫描了两次空间,第一次标记,第二次清除。
适用场合:
(1) 存活对象较多的情况下,比较高效;
(2) 适用于老年代:大部分都是存活对象。
(2)复制算法
复制的收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
缺点:
- 内存空间缩为原来的一半;
- 需要移动复制对象,较耗时
优点:
1)无内存碎片;
2)内存分配时,因为是连续的内存,只需要按顺序分配即可,分配速度快。
适用场合:
- 存货对象较少的时候比较高效;
- 适用于年轻代:基本上98%的对象都是朝生夕死的,存活率较低。
(3)标记-整理算法
标记整理算法是一种老年代回收算法,它在标记-清除算法的基础上做了一些优化。
首先,也需要从根节点开始对所有可达对象做一次标记;但之后,并不是简单的清理未标记对象,而是将所有的存活对象压缩到内存的一端,之后,清除另外一端空间。
这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,性价比比较高。但由于需要移动内存块,它依旧不是很适合存活率较高的老年代。
(4)分代收集算法
分代收集算法就是目前虚拟机使用的回收算法。
它将内存分为各个年代,一般情况下将堆区分为老年代、新生代。针对不同的代使用不
同的算法。
新生代存活率较低,可以使用复制算法;而老年代存活率高,没有额外空间对它分配担保,所以可以使用标记-清除算法或标记整理算法。
本节完!