Jvm虚拟机的垃圾回收机制
1. 垃圾回收发生在哪里?
首先就需要知道Jvm的内存结构了:有五种(方法区、堆、虚拟机栈、本地方法栈、程序计数器);new就进堆,堆存储对象数据,而垃圾回收主要是对内存中已经死亡或者长时间没有使用的对象进行清楚和回收来实现内存空间的有效利用,所以垃圾回收关注的重点区域在于堆。
2. 什么时候回收?
针对这一点有两个算法:引用计数器和可达性分析算法
引用计数器:
对对象的引用个数进行计算,增加一个引用+1,减少一个引用-1,当引用计数器为零时,表示对象没有被引用,那么在垃圾回收的时候,就可以被回收掉;
可达性分析算法:
主要根据GCRoots进行判断(GCRoots:只会引用其他队象,而不会被其他对象引用);通过GCRoots向下进行联通,可以联通的即还有用的对象,不能联通的即无引用的对象,可以被回收;
拓展
在JDK1.2之后,引入了强软弱虚四种引用状态:
- 强引用:与强引用相关联的对象,不会被回收
- 软引用:内存溢出时被回收
- 弱引用:只要发生垃圾回收就会被回收
- 虚引用:回收时获得一个通知
3. 怎样去回收?
标记-清除算法
先对可回收的垃圾进行标记然后再清理掉,清理掉的垃圾区域就成了未使用的内存区域,但是它有一个很严重的问题,会产生大量的内存碎片,会导致我们没办法去申请一个比较大的连续的内存空间。
复制算法
标记清除算法演化而来,解决了内存碎片问题,首先它将可用内存按容量来划分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了之后,就把还活着的对象复制到另一块上面去,然后再把已使用过的内存空间一次性清理掉,这样就保证了内存空间的连续可用,也解决了内存碎片的问题,但是也有一个问题,空间必须被拆分为两半,如果有10G内存空间,但是你能分配的最大单个对象却只有5G。
标记-整理算法
它的标记过程依然和标记清除算法一样,但是后续不是直接对可回收对象进行清理,而是让所有存活对象都向一端进行移动,之后再清理掉边界以外的内存区域。这个效率不高,对内存变动频繁,需要整理所有存活对象的引用地址。
分代回收算法
在融合以上三种基础的算法思想之后呢。就诞生了分代回收算法,严格来说,它只是一套组合而已。首先,根据对象存活周期不同,可用将JAVA堆划分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的算法。在新生代,每次垃圾收集时,都有大批对象死去,采用复制算法(效率高),在老年代,死得少,需要操作的次数就不是那么多,可以采用标记清除算法或者标记整理算法。
详细的分代回收以及处理可以看下方的原文,本文主要对网上查阅到的文章进行一个概述!
标签:对象,引用,回收,算法,内存,JVM,垃圾 From: https://www.cnblogs.com/weiboyaonuli/p/jvm.html注:本文主要对网上查阅到的文章进行一个概述
原文链接:https://blog.csdn.net/weixin_44196561/article/details/123908059