jvm垃圾回收知识总结

jvm垃圾回收知识总结

1.垃圾对象是如何确定的

主要是通过可达性算法分析,即通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的,可作为GC Roots的对象包括下面几种:
  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 方法区中类静态属性引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象。

2.垃圾回收算法

  • 复制算法
    把内存分为大小相等的两块,每次存储只用其中一块,当这一块用完了,就把存活的对象全部复制到另一块上,同时把使用过的这块内存空间全部清理掉,往复循环,缺点是实际可使用的内存空间缩小为原来的一半。这是新生代常用的算法。
  • 标记-整理算法
    在回收垃圾前,首先将废弃对象做上标记,然后将未标记的对象移到一边,最后清空另一边区域即可。
    这是一种老年代的垃圾收集算法。老年代的对象一般寿命比较长,因此每次垃圾回收会有大量对象存活,如果采用复制算法,每次需要复制大量存活的对象,效率很低。

3.jvm的分代回收

一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

目前大部分垃圾收集器对于新生代都采取复制算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间(一般为8:1:1),每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。

而由于老年代的特点是每次回收都只回收少量对象,一般使用的是标记整理算法。

  • Eden区没有空间进行分配时,将进行一次Minor GC。
  • 进行了Minor GC后,Eden还不足以为新对象分配空间(那这个新对象肯定很大),新对象直接进入老年代。
  • 当永久代的空间不足时,也会触发Full GC,如果经过Full GC还无法满足永久代存放新数据的需求,就会抛出永久代的内存溢出异常,java8移除了永久代。使用元空间,元空间直接在内存中。
  • 大对象(需要大量连续内存的对象)例如很长的数组,会直接进入老年代,
    如果老年代没有足够的连续大空间来存放,则会进行Full GC。

4.垃圾收集器

现在常见的垃圾收集器有如下几种

新生代收集器:Serial、ParNew、Parallel Scavenge

老年代收集器:Serial Old、CMS、Parallel Old

堆内存垃圾收集器:G1

每种垃圾收集器之间有连线,表示他们可以搭配使用。

参考

Java内存模型与垃圾回收

http://www.cnblogs.com/luoxn28/p/5492840.html

JVM知识点精华汇总 https://blog.csdn.net/huyuyang6688/article/details/81490570

你可能感兴趣的:(java)