本文源自Recently祝祝,创自Recently祝祝。转载请标注出处。
此解决方式在企业中有所应用,适合Java初级开发学习,参考。
本文字数与行数,耐性阅读必有收获。
堆内存结构
堆的内存结构:
- 年青代
- Eden区域:新建目标所在的区域
- Survivor0区:当Eden区域满的时分,进行一次Minor GC,存活目标进入Survivor0区,Eden区域存活目标会与Survivor区域合并
- Survivor1区:当Survivor0区满了,也会进行一次Minor GC ,存活目标复制进Survivor1区。Survivor1会依据目标年纪判断进入老时代还是继续复制到Survivor另一个区域里面。
- 老时代
- 老时代:当Eden区域创建的目标,MinorGC之后超越Survivor百分之五十内存的目标会进入老时代。通过15次Minor GC还存活的目标会进入老时代。
- 元空间:在1.8之后永久代被元空间替代。存取数据更灵敏。
为什么堆内存要分年青代和老时代?
-
主要原因–》分代搜集理论:将简单收回目标放入年青代,不简单收回目标寄存进入老时代。为了提高废物收回的功率,削减废物收回的频次和时刻。
-
依据分代搜集理论,分为强分代假说、弱分代假说。将简单消亡的目标寄存到弱分代中,存活时刻长的寄存到强分代中。为了功率更高的进行废物收回,依据生命周期的长短分为年青代和老时代两类。
-
年青代
- 年青代生命周期短,更简单被进行废物收回,需要更屡次的进行废物收回。
- 年青代分为三个区Eden区、Surivivor0区、Survivor1区。新创建的目标会先进入Eden区,当Eden区满了之后,会进行一次废物收回Minor GC,将存活下来的目标复制到Survivor0区,当Survivor0区满了,再次进行废物收回,存活下来的复制进入Survivor1区。Survivor1区满了,又复制进Survivor0区,循环往复。每复制进入Survivor区中年纪+1,当年纪达到15的时分就会被寄存到老时代。
-
老时代
- 生命周期长,更少的目标需要被收回,不需要频频的进行废物收回。
- 目标从年青代进入老时代,当老时代满了的时分,会进行一次Major GC ,全局废物收回。
-
老时代的Major GC与年青代的MinorGC 比较不需要那么频频并且但是耗时会更长,依据以上特点将内存区域分为老时代和年青代。
年青代进入老时代的整个过程
-
新目标请求–》
-
进入Eden区,判断内存大小是否能够寄存改目标–》
-
否,进行一次年青代GC,youngGC;是,寄存到Young区,分配目标内存–》
-
YoungGC之后看看Eden Survivor是否寄存得下,寄存得下就进入年青代Young区,寄存目标内存。—》
-
放不下则晋升为老时代,Old区放得下则分配目标内存;放不下则FullGC(对老时代的区域目标进行废物收回,也便是区域存满了,则进行整理,废物目标整理掉,获取内存) —》
-
FullGC之后查看Old区是否放得下,Old区放得下则分配目标内存;不然OOM—》
年青代中为什么会有两个Survivor区域
当Eden区满了之后,会进行一次废物收回Minor GC,将存活下来的目标复制到Survivor0区,当Survivor0区满了,再次进行废物收回,存活下来的复制进入Survivor1区。Survivor1区满了,又复制进Survivor0区,循环往复。
- 由于大部分新目标很快就会被开释,所以将它们分配到一个时刻短的区域(Eden)中能够有效地削减废物收回的频率。
- 将Survivor区划分为两个部分能够交替使用,然后削减了废物收回时需要扫描的目标数量,然后削减了废物收回的时刻。
文章全为个人理解,如果发现部分跟你所知道的有出入,欢迎在评论区指出,欢迎探讨。