GC:你要用什么方式把我丢掉?
引用的对象以蓝色显卡。未引用的对象以金色显示。在标记阶段扫描所有对象以进行此确定。如果必须扫描系统中的所有对象,这可能是一个非常耗时的过程。
Step 2:清除(Normal Deletion):
清除阶段移除掉对象垃圾,并且用一个链表维护空闲的区域
内存分配器持有空闲内存区的引用,以便分配内存给新的对象
优点:
每个活着的对象的引用只需要找到即可,找到一个就可以判断它为活得。不用移动对象的位置。
缺点:
效率比较低(递归与全堆对象遍历),每个活着的对象都要在标记阶段遍历一遍。
所有对象都要在清除阶段扫描一遍,算法复杂度高。
没有移动对象,导致可能出现需要碎小的空间无法利用(可能导致空间利用率低)。
[](()标记-压缩算法
基于标记-清除法的缺点—无法利用碎小的空间,提出了我们的标记-压缩算法。不同之处在于在第二个阶段,该算法并没有直接堆死亡的对象进行清理,而是将所有存活的对象进行整理,放在同意区域的另一处空间,然后把剩下的所有对象全部清除,这样就达到了标记-整理的目的。
通过一起移动引用的对象,这使得新的内存分配更容易和更快
优点:
不会产生大量的碎片空间
缺点:
如果存活的对象过多,整理阶段就会执行较多复制操作,导致算法效率低。
[](()复制算法
复制算法与标记-压缩算法的不同之处在于不是在同一个区域进行复制,而是将所有存活的对象复制到另一个区域。
该算法将内存平均的分为两个部分,然后每次使用其中的一部分,当这部分内存存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只是用这部分内存,然后循环。
优点:
实现简单,不产生内存碎片
缺点:
每次运行,总有一半内存是空的,导致内存的利用率只有 50%。
[](()分代收集算法
标记和压缩算法存在的问题
标记和压缩算法对 java 虚拟机而言会比较耗时。当 java 虚拟机分配了越来越多的对象之后,GC 就会花费更多的时间。然而,绝大多数的对象存活时间都比较短。这样我们可以把存活时间长的对象和短的对象隔离开。GC 就会拥有更高的效率。
Y 轴显示分配的字节数,X 访问显示随时间分配的字节数。
随着时间的推移,分配的对象越来越少。事实上,大多数物体的寿命都很短。
现在的虚拟机 GC 大多数采用分代收集算法,它根据对象的生存周期,将堆分为新生代和老年代。
分代收集算法思想:
在新生代中,由于对象生存期短,每次回收都会有大量的对象死去,那么这时就采用复制算法。
老年代里的对象存活率高,没有额外的空间进行分配,所以可以使用标记-清除或者标记-压缩进行清除。
分代收集过程
新生代(Young)分为 Eden 区。From 和 To 区
2.几乎所有新的对象都会在 Eden 空间分配内存,两个 survivor 空间一开始都是空的。
3.对着对象的不断创建,Eden 区被填满
4. 当 Eden 区满的时候,就会触发一次 Minor GC(Young GC),也就是新生代的垃圾回收,所采用的是复制算法。
Eden 空间的存活对象将被复制到第一个空间,年龄+1,S0 中的 1 代表年龄。
5.新创建的依然会被放在 Eden 区,当再次被填满时,会再一次触发 Minor GC,此时会同时将 Eden 区和 S0 区的存活对象都复制到 S1 区。
![在这里插入图片描述](https://img-blog.csdnimg.cn/663f82b8297b4ba2b0a86f4a02fc5abd.png?x-oss-process=image/watermark,type_d3F5L 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 XplbmhlaQ,shadow_50,text_Q1NETiBAVml2aWVuX29PMA==,size_20,color_FFFFFF,t_70,g_se,x_16)
6.同样再一次触发 Minor GC 的时候,又将共同的存活对象赋值到 S0 区。
7.随着 Minor GC 的不断发生,随着在幸村区的不断交换,有的存活对象的年龄在不断增加,当幸存对象的年龄到达指定的阈值时,会被移动到老年代。(阈值由 JVM 参数决定,此处为 8)。
8.当老年代的内存被填满时,将会触发 Major GC (Full GC)进行老年代的内存清理。Majoe GC 在老年代用的时标记-清除算法。同时新生代的对象将被清除。
做一次 Major GC 要比进行一次 Minor GC 时间更长,一般为 10 倍以上。
[](()对象被放置到老年代的条件
评论