名词解释
·部分收集(Partial GC):指目标不是完整收集整个Java堆的垃圾收集,其中又分为:
新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。
老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。另外请注意“Major GC”这个说法现在有点混淆,在不同资料上常有不同所指,读者需按上下文区分到底是指老年代的收集还是整堆收集。
混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。
·整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。
这是引用得那个 深入理解Java虚拟机(第3版),周志明,机械工业出版社中得解释
3.3.1分代收集理论
垃圾回收针对的是堆区域,主要是对对象的回收。
堆区域的分区:新生代,老年代
分代收集理论建立在两个假说之上:
1)弱分代假说:绝大多数对象都是朝生夕灭的。
2)强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。
收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。
新生代就是内存中绝大多数对象就是朝生夕灭的,当回收新生代内存时,可以只关注保留哪些对象就可以了,对保留对象以外的对象直接进行回收。老年代中的对象大多经过多次收集而不被回收的,所以可以不用那么频繁的对老年代进行回收。
分代收集理论存在的问题:跨代引用
跨代引用:就是有可能存在老年代引用新生代的情况。
相互引用的两个对象应该是同时消亡的,当我们要回收一个被老年代中对象引用的新生代中的对象时,我们除了回收新生代中的对象,还要去遍历整个老年代。由此出现了第三条假说:
3)跨代引用假说(Intergenerational Reference Hypothesis):
跨代引用相对于同代引用来说仅占极少数。
当一个新生代对象被老年代对象引用时,这时新生代对象就不会被轻易回收,慢慢的就变成了老年代,当新生代对象变为老年代对象就消除了跨代引用了。
这是就用一个数据结构(记忆集)记录哪些对象存在跨代引用,当进行老年代回收时就去扫面这个结构。
当前我们使用的是G1收集器,分区域回收,一块一块的回收就不用暂停所有的线程了,暂停正在收集的区域的线程就可以了。
三种垃圾收集算法:
3.3.2 标记-清除算法
算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象,也可以反过来,标记存活的对象,统一回收所有未被标记的对象。标记过程就是对象是否属于垃圾的判定过程
缺点:
-
- 随着堆内存中的对象数量的增多而导致需要大量标记和清除操作从而导致的执行效率降低。
- 会产生大量的内存碎片,导致以后分配较大内存对象时找不到连续内存空间。
3.3.3 标记-复制算法
将内存分为大小相等的两部分,一次只使用一部分,当进行垃圾收集时,就把正在使用的内存中还在存活的对象复制到另一块内存上,再回来对整个内存进行垃圾回收。
缺点:
-
- 如果存活的对象过多,那么复制这些对象的开销太大。
- 空间浪费过多,一次可用的内存只有一半大小。
现在商用虚拟机(1.7以前针对新生代)采用的是,复制标记算法的改版:就是分成三个区域:一块Eden空间(占总空间的80%),两块Survivor空间(每块占总空间的10%)。每次空间回收将存活的对象放到另一块Survivor空间上。这样就能保证90%可用空间了
3.3.4 标记-整理算法
和标记-清理算法类似,就是将不需要被清理的对象向内存的一侧移动,然后找到需要清理和不需要被清理的界限,界限到另一侧直接清理。
标记-整理算法和标记-复制算法的对比:
标记整理是在自己的内存上不需要另一块内存,但是整理过程麻烦,内存利用率高,性能慢
标记-复制算法是直接复制过去,整理简单,但是对内存的损耗太大,性能块,内存利用率低
对于老年代来说,每次需要移动的对象太多,负重太多
3.4.1根节点枚举
就是根节点一个个去查询,垃圾回收过程中其他线程得停止,如果不停止其他线程的话就会出现冲突,就是垃圾回收机制将这个对象标记为无效,但是其他线程又往这个对象中写入数据,但是还是会被清理掉,就会产生冲突。垃圾回收会与我们当前的线程存在并发问题。
参考:
深入理解Java虚拟机(第3版),周志明,机械工业出版社