jvm内存模型与GC回收(理论篇)

首先我们来看一下jvm内存模型图:
在这里插入图片描述
程序计数器:
程序计数器主要作用是记录当前线程要执行的字节码指令的内存地址。如果正在执行的是Native 方法,则这个技术器值为空(Undefined)

虚拟机栈:
虚拟机栈主要用于存储储局部变量表,操作数栈,动态链接,方法出口,每一个方法调用都是入栈到出栈的过程,也就相当于方法调用运行,如图:
在这里插入图片描述
首先:
0:iconst_1 将int类型的1压栈 ——》1:istroe_1将int类型的1出栈,同时存入局部变量表中,变量名为a ——》2:iconst_2将int类型的2压栈 ——》3:istroe_2将int类型的2出栈,同时存入局部变量表中变量名为b ——》4:iload_1从局部变量表中索引为1的值压栈(也就是a)——》5:iload_2从局部变量表中索引为1的值压栈(也就是b)——》6:iadd将栈顶中2个变量进行求和 ——》7:istore_3将求和的值存入变量表,变量为c ——》8:iload_3将存入的局部变量表c的值压栈 ——》9:ireturn栈顶元素出栈,返回结果。
这边运行个人总结应该就是变量需要进行使用的时候,变量首先要压栈然后,运行获取结果在出栈返回数据。

本地方法栈:
本地方法栈跟虚拟机栈类似,主要本地方法栈存储不属于java类型的数据,比如c#或者其他类型的方法。使用native字段进行声明。

方法区:
方法区主要存储类信息,常量,接口,方法,字段等等,同时方法区是被所有线程共享的,方法区和java堆是连在一起的是相互隔离的,但是它们的物理内存是连续的,永久代也称之为方法区和老年代是相连的,如图:
在这里插入图片描述在jdk1.7版本以前(包括1.7)方法区称为永久代,在jdk1.8以后方法区修改为元空间,那么为什么jdk1.8以后永久代修改为元空间呢,小博主个人总结了几点(觉得不合适的欢迎评论了):
1:在jdk1.7时老年代进行垃圾回收时,同时会对永久代进行回收,其实这样也是对性能的消耗,而在jdk1.8时修改为原空间以后老年代就于原空间进行分离,不在进行垃圾回收如图:
在这里插入图片描述
2:在jdk1.7是需要对方法区设置内存大小,如果设置小了容易导致OOM内存溢出异常,而在jdk1.8是,我们可以不用设置方法区的内存,因为它会根据我们系统的内存大小来进行自动分配,同时也会不断扩充内存大小,直到系统内存不够用。

java堆
java堆存储的主要是对象实例和数组,同时它也是JVM管理中最大的一块区域也是GC回收的主要区域,如图:
在这里插入图片描述
Eden S0 S1 老年代都代表什么意思呢:
Eden S0 S1 这三块区域为年轻代:在新的对象加入java堆时,它们的内存分配为8:1:1,首先进入的是Eden区,Eden区也是堆中最活跃的区域,在Eden区存储空间满时,会触发垃圾回收机制,在垃圾回收时首先检查你的Eden区,将Eden区存活的对象放入S0区,如果S0区满了,那么则将eden区和S0区存活对象复制到另一个S1区,然后清空eden和这个S0区,此时S0区是空的,然后将S0区和S1区交换,即保持S1区为空, 如此往复。
如上这样,反复复制达到15次以上就会进入到老年代中,老年代主要存储的就是经常被时候的对象,如果老年代也满了,就会触发一次Full GC(Major GC),也就是新生代、老年代都进行回收。

java堆GC7种垃圾回收器:

1:Serial串行收集器:
在这里插入图片描述
Serial是单线程收集器,只会用一个CPU或一个线程去完成垃圾回收工作;并且在进行垃圾回收时,必须暂停所有其他的线程,直到收集结束为止。采用复制算法。

2:Serial old收集器主要回收老年代空间,于Serial收集器工作模式一致

3:parNew并行线程收集器
在这里插入图片描述
parNew并行线程收集器算是serial多线程版本,如果是多线程的情况下使用perNew收集器性能会比较好,如果是单线程的情况下serial优势较大,同时目前只有它能于CMS收集器进行配合工作。采用的是复制算法。

4:Parallel Scavenge 并行线程收集器:
在这里插入图片描述
Parallel Scavenge收集器关注点是达到一个可控制的吞吐量(吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)),而其他收集器关注点在尽可能的缩短垃圾收集时用户线程的停顿时间。
Parallel Scavenge收集器提供了两个参数来用于精确控制吞吐量,一是控制最大垃圾收集停顿时间的 -XX:MaxGCPauseMillis参数,二是控制吞吐量大小的 -XX:GCTimeRatio参数;主要用于后台计算不需要太多交互的任务。

5:老年代收集器-Parallel Old:
主要Parallel Scavenge收集器配合使用,真正形成了吞吐量优先的组合采用的是标记整理算法。

6:老年代收集器-CMS
在这里插入图片描述
CMS收集器目的就是将垃圾回收时间降低,对于B/S架构系统互联网,要求服务器响应较快的比较合适。它工作分为4步:
1:初始标记:将单线程进行标记,速度很快但是会暂停所有线程
2:并发标记:将初始标记完毕的线程进行可达分析,分析该对象是否需要被回收,该过程是并发运行的。
3:重新标记:为了修正并发标记期间因用户线程继续运行而导致标记发生改变的那一部分对象的标记记录。会暂停所有线程,但是停顿时间短
4:并发处理:清除需要回收的对象,该过程是并发运行的。
我们看到CMS收集器步骤是较为复杂的,但是它将我们垃圾回收的过程细化了,并且优化了垃圾回收需要等待的时间。
个人总结6种垃圾收集器运用场景:
Serial+Serial Old:适用于单线程系统,因为它们工作模式就是单线程模式。
ParNew+CMS:适用于B/S系统,用户交互性强的系统,CMS极大的优化了垃圾回收等待时间。同时parNew是多线程工作模式,更加快速进行垃圾回收处理。
Parallel Scavenge + Parallel Old:主要适用于交互少,计算多的系统,因为它们主要关注点是可控制的吞吐量,控制垃圾回收的停顿时间。

G1收集器:
G1收集器,像别的收集器基本都是年轻代一个收集器,老年代一个收集器而G1将真的年轻代和老年代整合在一起了,同时它使用的是标记-整理算法,这样就不会出现内存碎片,具体如图:
在这里插入图片描述
它的空间划分成一个一个的小块,Eden为年轻代,Survivor为幸存区,Old为老年代,Humongous大存储空间,NoUse可用空间。当一个新对象进入时,首先存入Eden区域。

G1垃圾收集器核心-Card和Rset:
在G1创建时,每一个Eden,old,survivor,noUse,Humongous都是Region,每一个Region中都分为了多个Card,平均每个card大小为512bytes,如图:
在这里插入图片描述
region中的每一块都是card,红色的card代表使用根空间,指向的绿色的card为被引用的空间(被红色引用的空间)。下面的RSet则是记录红色card的空间地址,为什么要这么做呢?

主要还是跟G1的垃圾回收相关,在G1的垃圾回收过程中有两种垃圾回收:
Young Gc:youngGC收集器主要为Eden和Survivor区的数据,当Eden区存储满时,会触发young GC垃圾回收,这时Eden区域存储的数据将移入Survivor区域,如果Survivor空间不够,Eden空间的部分数据会直接晋升到年老代空间。其它数据则存入新的Survivor空间中。同时它运行阶段如下:
1:本地对象和静态的扫描
2:将扫描完毕的本地对象和静态更新到RSet里面,G1不可能实时更新Rest里面引用关系,所以第二部更新RSet。
3:在RSet引用关系数据中检测年轻代指向老年代的数据,将数据记录到Cset集合中
4:将处理完的对象复制到survivor或者old中

Mixed GC:Mixed GC收集器是进行全局数据回收,当old区的对象占总Heap的比例超过阈值(默认45%)之后,就会开始并发标记(Concurent Marking), 完成并发标记后,G1会从Young GC切换到Mixed GC。它的运行阶段如下:
1:初始标记–>暂停所有线程,获取到YoungGC中扫描的对象结果。
2:根区域扫描–>通过Young GC中获取的对象找出所有的GC Roots的Region, 然后从这些Region开始标记可到达的对象。
3:并发标记–>在整个堆中查找可访问的对象。
4:最终标记–>处理缓冲区(采用标记算法),跟踪未被访问的存活对象。
5:清除垃圾–>在这个最后阶段,G1 GC 执行统计和 RSet 净化的 STW 操作。在统计期间,G1 GC 会识别完全空闲的区域和可供进行混合垃圾回收的区域。

里面最关键的还是RSet,RSet主要的作用就是去记录每一刻Card中数据的引用,在垃圾回收时,只需要扫描Rset就可以,不需要进行全局扫描。大大提升了回收性能。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

戴~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值