jvm垃圾回收算法

引用

  强引用:这个引用在程序代码间很常见,类似于Object a=new Object(),这样直接声明的对象,只要强引用还存在,那么这个对象就不会被gc回收。
  软引用:java用SoftReference类来实现软引用。软引用关联的对象会在系统即将发生内存溢出,也就是内存不够时,将会把这些对象进行回收,如果回收后依旧没有足够的内存才会抛出内存溢出异常。
  弱引用:java用WeakReference类实现弱引用,其强度更弱于软引用,被弱引用的对象会在下次垃圾回收时直接被回收,无论内存是否足够。
  虚引用:java用PhantomReference类来实现虚引用。这个是最弱的一种引用,甚至无法通过虚引用来获取对象。

判断对象是否被引用

引用计数算法

  给对象加一个引用计数器,每当一个地方引用它时,计数器就加一,当引用失效时,计数器就减一,任何时刻计数器为0时的对象就是不可能再被使用的。但是有bug,2个对象相互引用,那么这个对象就永远无法被回收。

可达性分析算法

  这个算法是通过一个叫”GC Roots”的对象作为起始点,从这个节点开始向下搜索,搜索的路径叫做引用链,如果可以通过引用链找到这个对象,那么这个对象时有效的,否则,无效,解决了上面2个对象相互引用但是没有别的对象可达的问题,可以作为”GC Roots”的对象有方法区常量引用的对象,虚拟机栈引用的对象,等。目前java就是这种判断模式。

gc垃圾回收算法

标记-清除算法

  最基础的算法,就是把要回收的对象标记后进行回收,缺点是容易产生大量不连续的内存碎片,如果产生一个大的对象时,由于全是内存碎片,没有整个的内存,因此内存不够就会提前触发垃圾回收,效率很低。

复制算法

  目前主流虚拟机的收集算法之一主要针对新生态对象,初始化时是一比一的算法,就是把内存分为2部分一样大的部分,平时只使用其中一个部分也就是其一半,当发生垃圾回收时,就会把这个部分存活的对象放到另一个部分,这样子就避免了内存碎片,但是要只使用一半的内存,亏损太大划不来,目前主流虚拟机都是用这个算法来回收新生代。IBM研究发现,98%的新生态对象生存周期很短的,于是一个新的算法出来了,就是把内存分为3部分,8:1:1,每次使用其中的0.9部分,当发生垃圾回收的时候那就把剩余的对象就放到剩余的0.1那里,当然剩余的0.1可能不够那就可以把一部分对象转化为老年态暂时存到老年态里面,这样子就只浪费0.1的内存了,性价比可以。

标记-整理算法

  主要针对老年态对象,由于生存周期较长,不适合复制算法,该算法就是和标记-清除算法的加强版,就是多了一个移动的算法,就是把存活的对象都向一端移动,并且把端边缘的字段干掉

分代收集算法

  就是把对象划分为新生态和老年态,不同态使用不同不同的收集算法,新生代采用复制算法,老年态使用标记-整理算法或者标记-清除算法,这个也就是主流虚拟机所采用的。

垃圾回收器

  垃圾回收器就是垃圾回收算法的具体实现,我们看看都有哪些垃圾回收器。

serial收集器

  一个单线程的垃圾回收器,它在进行垃圾回收时,会让其他所有线程都暂停,直到他垃圾回收完毕,很显然,问题很大。采用的是复制算法。回收新生代对象。

parnew收集器

  是serial收集器的多线程版本,没有其他本质的区别

parallel sacvenge收集器

  这是个新生带收集器,采用的是复制算法。

serial old收集器

  采用标记-整理算法。单线程。主要配合serial收集器

parnew old收集器

  主要是配合parallel sacvenge收集器这个新生代垃圾回收器使用。

cms收集器

  也是老年态收集器,采用标记整理算法。

G1收集器

  上述收集器都要相互配合才可以使用,一个负责收集新生代对象,一个负责收集老年态对象。
  但是这个G1不一样,这是个面向服务端的垃圾回收器。
  以下优势:
  1.能充分利用多核CPU来减少暂停时间。
  2.分代收集,自身就可以实现分代收集。
  3.空间整合:整体是采用标记-整理算法实现的收集器,但是局部上也是基于复制算法实现的。
  4.可预测的停顿:让使用者在一定时间内消耗的垃圾回收时间不超过n毫秒。
  其他垃圾回收器回收要么是新生代,要么是老年代,但是G1不一样,虽然依旧保留了新生代和老年代这个概念,但是实际上将这个java堆分成了多个大小相等的独立区域Region,新生代和老年代不再是物理隔离了。他们都是一部分Region的集合(不需要连续)。
  G1使用了一个方法来进行可预测的停顿,G1会跟踪每一个Region堆的垃圾回收价值(回收可用空间和对应时间),并且维护一个优先列表,当需要进行垃圾回收时就按照这个优先列表来处理。

GC

  1.这个Minor GC是针对年轻代的回收,当虚拟机无法为一个新生对象分配空间时。就会发生这个GC操作。
  2.Major GC 是清理老年代。Full GC 是清理整个堆空间—包括年轻代和老年代
  3.每一次GC都会使得整个程序暂停几毫秒,这对用户程序几乎没有反应。

规则

  目前虚拟机,老年代:新生代=2.27:1。
  新生代,eden:from:to=6.4:1:1。
  对象优先在eden区分配,大对象直接进入老年代(经历了多个gc存活的对象,from,to,大于某个年纪的对象总和大于其一半时,将其也挪到老年代。),长期存活对象将进入老年代。
  当给对象分配内存时,如果没有足够的空间分配,虚拟机将发起一次垃圾回收。垃圾回收后,还是不够的话,会根据分配担保机制。就会把eden区的数据丢到老年代里面去。