《java编程思想》读书笔记——第一章1.7对象的创建和存在时间sp2(java堆、堆GC机制及过程,对象的一生)
作者:互联网
1.6堆内存
1.其存储方式为随机存储,存入时,需要先寻找会存放的区域,因此存取速度较慢,其存取算法与栈不同,并不需要具体的数据存在时间
2.堆可以动态扩容,其大小上限由参数-Xmx(最大内存)和-Xms(初始内存)决定,因此可以用于存放一些在代码编写时并不确定具体大小的数据(比如我的对象是一个符合某种特征的列表,可能是一个非常大,且我并不能确定其大小的对象),但是当其扩容到极限时,依然会报oom错误
3.综合以上两种特性,java认为堆适合用于存放对象,实际上堆也只用于存放对象,继而,出现了新的问题,我们已知内存并不是无限的,而程序员并没有指定对象的具体存活时间,因而,堆内存的清理是一个常见的议题
4.在java中堆内存的清理交付于垃圾收集器机制,其为了提高清理效率使用了分代算法对堆中的对象进行清理,如图中所示,其被分为新生代和老年代,其中新生代又可继续细分为Eden、survive to和survive from
5.堆内存发生的GC有两种发生于新生代的MirrorGC和老年代爆满后触发的FullGC,其中,FullGC所要话费的时间是MirrorGC的10倍以上
pass:为什么FullGC慢?:关于效率我们很简单就会想到时间与空间的转换,主要原因有两个:
5.1.MirrorGC用空间换了时间,其本质为复制算法,即空间分割为两个部分,新建只使用一部分,装满后直接将还活着的对象复制至另一部分,然后将其他部分直接全部清空,直接复制的速度很快的同时,没有空间整理的过程,而且,每次进行该算法时存活的对象其实非常少,因此产生了8:1:1的eden和survive的结构比例,所以需要用来换时间的空间成本其实很低
5.2.FullGC用时间换了空间,其本质为标记清除算法,因为老年区中大部分的对象都处于长期活跃状态,这导致复制算法的效率低下不适合使用,底层是通过根搜索法,将所有的活跃对象标记,之后将未标记的对象全部删除的过程,这会产生大量的碎片空间,因而fullGC还需要对碎片空间进行一次排序整理
6.一般来说,新建的对象将会出生在新生代——但是,若一个对象的体积过大,将会直接出生在老年代,而且,将会导致只有FullGC才可以将其清除 ,且若将会持续的产生这种大对象,将会导致频繁的FullGC而使得程序卡顿
7.详细讨论GC过程,为了更加透彻的讲解,我将以模拟现实的运行场景的顺序讨论
7.1.大量的对象在eden中诞生,因而eden内存很快就会被占满,由于大部分的对象朝生暮死,此时,只需要把已死亡的对象进行清除即可
7.2.如图所示,mirrorGC被触发后,Eden和Surive From区内的存活对象将会被复制到Surive to区域,之后,除了Surive to以外的两个区域全部直接清空,并且Surive to将会和Surive From交换引用,即存放了存活的对象的区域更名为Surive From,并且这些经过了一轮MirrorGC依然活着的对象,其年龄计数器将会+1,默认来说,年龄至15时,将会进入老年区
7.3.如图所示,Eden再次爆满,再次触发mirrorGC,循环该流程,15岁以上的对象复制至老年代
7.4若老年代爆满,全部内存开始执行FullGC,若依然爆满,将会报出oom错误
标签:1.7,java,Surive,读书笔记,对象,将会,算法,FullGC,内存 来源: https://blog.csdn.net/qq_41445205/article/details/104104614