日常记录——JVM—垃圾定义、垃圾寻找、基本垃圾回收方法、堆内存逻辑分区

一、垃圾定义

一个没有引用指向的对象,就是垃圾。可以理解为断了线的风筝。

二、垃圾寻找

1.引用计数法:有一个引用指向该对象,该对象头部的计数器加一,失效就减一,为0则代表垃圾。java不使用该方法,该方法存在循环引用问题,A指向B ,B 指向A 。则 A B 的计数器最小为1,不会回收。
2.可达性分析法:通过一系列名为GC Roots的对象作为起始点,不在GC Roots的引用连路上的对象则为垃圾。GC Roots对象:线程栈变量(方法的局部变量),静态变量(class的静态变量),常量(calss的常量),Native本地方法引用的对象。

三、基本垃圾回收方法

1.标记清除:首先标记垃圾对象,然后清除。
回收前:
在这里插入图片描述
回收后:
在这里插入图片描述
在这里插入图片描述
优缺点:存活对象多时效率高,需要两次扫描,首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象,清理结果会产生碎片区域,分配大对象找不足够的连续内存,会触发gc。
2.复制:将内存分为两块,每次存储对象只使用一块,执行算法时将还存活着的对象按序复制到另外一块上面,然后将前一块全部清理。
清理前:
在这里插入图片描述
清理后:
在这里插入图片描述
在这里插入图片描述
优缺点:存活对象少效率高,无内存碎片,只扫描一次,但内存利用率低。
3.标记压缩:与标记清除类似,但标记后不是对垃圾进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
清理前:
在这里插入图片描述
清理后:
在这里插入图片描述
在这里插入图片描述
优缺点:需要扫描两次。一次标记垃圾,一次移动,效率低,但内存无碎片且内存使用率高。
4.分代算法:Java堆可分为年轻代和年老代。年轻代代每次垃圾回收会回收大量垃圾对象,只有少量存活,可用复制算法,只需要付出少量存活对象的复制成本内存就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保并且可能是大对象,就必须使用“标记-清理”或“标记-整理”算法来进行回收。

四、堆内存逻辑分区

在这里插入图片描述
年轻代:eden伊甸区、survivor幸存区2个,比例为8:1:1。eden区存放新new出来的对象,survivor存放垃圾回收后幸存下来的对象,两个幸存区做复制,还有一块是线程本地分配区域TLAB(Thread Local Allocation Buffer),线程独享,防止并发争抢内存,只占1%。年轻代空间耗尽触发YGC(MinorGC)。
年老代:存储年轻代存活15次的对象,大对象直接进入年老代,Survivor空间中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入年老代,YGC时,survivor区不够分配也进入年老代。年老代无法继续分配空间触发MajorGC(FullGC),年轻代年老代同时回收。
年轻代和年老代内存比例为 1:2

猜你喜欢

转载自blog.csdn.net/weixin_43001336/article/details/107520998