Java虚拟机内存存储结构以及GC回收算法的浅析

xiaoxiao2021-02-28  11

JVM内存结构:

堆:存放所有new出来的东西。GC堆是Java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域。堆被分为新生代和老年代。

方法区:存储虚拟机加载的类信息,常量,静态变量,各个内存共享的内存区域。默认大小为16mb,最大值为64mb

虚拟机栈:描述的是Java方法执行的内存模型。每一个方法被执行的时候,都会创建一个“栈帧”,用于存储局部变量表,操作栈,方法出口等。

本地方法栈:为Native方法服务。

程序计数器:分支、循环、跳转、异常处理、线程恢复。

JVM启动流程:

JVM基本结构:

GC回收机制:

判断对象是否存活:

1.引用计数:每个对象都有一个引用计数属性,新增一个引用时计数加1,引用释放时减1,计数为0的时候可回收。

2.可达性分析:从GC Roots开始向下搜索,搜索所走过的路径称为引用链,当一个对象没有任何引用链相连时,则该对象不可用,回收。

GC回收的四个算法:

1.标记-清除算法:该算法分为两个阶段:

1>标记阶段:找到所有可访问的对象,做个标记

 2>清除阶段:遍历堆,找到未被标记的对象回收

优点:

1>可以解决循环引用的问题

2>必要时才回收

缺点:

1>回收时,应用需要挂起,也就是stop the world.

2>标记和清除的效率不高,尤其是扫描的对象比较多的时候

2.复制算法:

首先将内存分为大小相等的两部分(假设A、B两部分),每次呢只使用其中的一部分(这里我们假设为A区),等这部分用完了,这时候就将这里面还能活下来的对象复制到另一部分内存(这里设为B区)中,然后把A区中的剩下部分全部清理掉。

优点:

吞吐量大,只需要遍历一次From空间Sweep需要遍历两次,而且只复制存活的对象。高速分配,不需要通过空闲链表直接在连续的内存上进行分配。没有碎片。与缓存兼容,复制存活对象时采用深度优先算法使相关联的对象都在附近。

缺点:

堆的使用效率低,必须分配一个To,其不能分配对象。不兼容保守式GC算法,需要移动对象。递归调用,复制对象的深度优先算法是通过递归调用实现的,递归将消耗栈等资源。

3.标记-整理算法:算法不直接对可回收对象进行清理,而是让所有可用的对象都向一端移动。然后直接清理掉边界意外的内存。

4.分带收集算法:

根据对象的存活周期不同将内存划分为新生代和老年代,存活周期短的为新生代,存活周期长的为老年代。这样就可以根据每块内存的特点采用最适当的收集算法。 

新生代的中每次垃圾收集中会发现有大批对象死区,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。  老年代中因为对象的存活率高,没有额外的控件对它进行分配担保,就必须使用“标记-清扫”或者“标记-整理”算法来进行回收。
转载请注明原文地址: https://www.6miu.com/read-2250042.html

最新回复(0)