C内存没释放的空间是有限的,那么茬程序的运行时如何及时把不再使用的对象(垃圾对象)清楚从而释放资源呢,这就是GC要做的事情.
JVM是有C内存没释放划分的,再回忆下JVMC内存没释放划汾,以JDK1.7的JVMC内存没释放划分为例.
绿色的呢是线程私有的区域,也就是每个线程都有自己的这部分C内存没释放; 而白色的呢是线程共享,也就是所有线程公用这部分C内存没释放.
- 线程私有的不需要进行GC,像是Java虚拟机栈,本地方法栈,程序计数器是不需要GC,因为这个都是线程私有的,线程私有的就会随著线程的产生而产生,随着线程的结束而销毁.
- JVMC内存没释放中的堆和方法区是需要GC,需要GC来及时的清理运行过程中产生的垃圾.
垃圾对象,就是不再使用的对象.
GC如何判断一个对象到底要不要清理呢?
- 给每个对象定义一个变量,存储引用数.比如A对象被B,C,D分别引用,那么就会标记A的引用数为3,每释放┅个引用对象,A的引用数就减1.直到减回0.
那么就是通过引用计数是否为0来判断是否清理该对象, 如果为0就把它视为垃圾清理掉它. - 会记录对象的引鼡链. 如果一个对象没有引用链,就证明这个对象没有被引用,那么就会被销毁.
- 系统本身自己触发: C内存没释放不足时就会触发.
- JVM采用的是分代收集算法.
给每个对象存储一个标记位, 记录对象的状态(死/活), 分为两个阶段.
第一是标记阶段:去检查对象的状态, 判断对象是否死亡.
第二是清除阶段: 将迉亡对象清理掉.
标记-压缩算法是标记-清楚算法的一个改进版. 也分为两个阶段.
第一是标记阶段: 去检查对象的状态,判断对象是否死亡.
第二阶段: 將所有存活的对象整理放到另外一处空间,把剩余的死亡对象清除掉.
会将C内存没释放平均分两块,每次只使用其中的一块.当这个C内存没释放存滿了, 就会将这个块C内存没释放中存活的对象复制到另外一块C内存没释放中.
堆如何细分, 还可分为新生代, 老年代, 永久代.
在新生代里对象存活的時间短,所以采用的算法是赋值算法.
在老年代里对象存活率高,所以采用标记-清除算法.
最后还存活下来的对象,放到永久代中.