JVM之GC

判断对象需要回收:1.引用计数法:给对象加上一个计数器,当有一个地方引用它,

                计数器+1,引用失效时,计数器-1,当计数器为0时,判定该对象可回收

          此方法无法检测循环引用 导致内存泄漏

          

//循环引用

public class MyObject{
   public MyObject chlid;  
}

public class Main{
public static void main(String[] args){
  MyObject o1 = new MyObject();
  MyObject o2 = new MyObject();
  o1.child = o2;
  o2.child = o1;    
}
}

         2.可达性算法:指通过称为GC-Roots的对象为起始点,从这些结点向下搜索,

                当从GCRoots到这个对象不可达时,被判定为可收回的对象

            可作为GC ROOTs:栈中引用对象,方法区中静态属性和常量引用对象

finalize()方法:  当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。

四大引用:强:普遍存在,引用在就不回收引用对象

     软:softReference,有用非必须,内存溢出前回收

    

  String str = new String("aaa");//强引用
        SoftReference<String> softRef = new SoftReference<String>(str);//软引用

     弱:weakReference,非必须,下一次GC一定回收

     虚:phantomRenference,不能取得对象实例,为了回收时收到系统通知而设置

回收方法区即永久代的回收:回收废弃常量(无对象引用)和

      无用的类(所有实例化,类加载器被回收,反射无法访问)

回收算法:1.标记清除:先标记(可达对象)再清除,效率低,产生大量内存碎片,可能提前触发GC

     2.复制:内存分成两块,用一块,之后把存活对象复制到另一块,再把这块清理;

          回收新生代就是这个策略,但是具体分为3部分(8:1:1)

     每次使用Eden和其中一块Survivor区。也就是说新生代可用内存为新生代内存空间的90%。

     3.标记整理: 标记活的对象,让他们向一端移动,然后清理边界以外内存,用在老年代

      4. 分代:堆分为新生代,用复制,老生代用标记整理   GC有两种方式  Minor GC(针对新生代),Eden空间不足触发 和 Full GC(针对新生代和老生代)1.老年代空间不足,2.Minor GC晋升到老年代的平均大小大于老年代剩余空间 3.System.gc() 会触发

stop the world: JVM由于要执行GC而停止了程序的执行  GC Roots可达性分析时,要使整个执行系统看起来像被冻结在某个节点,保证结果正确性

  虚拟机采用OopMap的数据结构直接得知哪些地方存着对象引用

安全点:记录OopMap,程序中可安全进行GC的地方,选那些可让程序长时间执行的点,比如方法调用,循环,异常跳转

GC发生时让所有线程跑到安全点的方法:抢占式中断(不用),暂停线程,恢复不在安全点的线程,让它们跑到安全点。

                  主动式中断:线程均设一个标志,轮询发现为真就挂起自己,轮询标志的地方就是安全点

安全区域:引用关系不发生变化的区域,GC安全,“扩大的安全点”

垃圾收集器:CMS:基于标记清除(老年代),极大缩短停顿时间  初始标记--并发标记--重新标记--并发清除(清理垃圾对象  程序不会停顿)

      G1: 分代收集,局部来讲基于复制,将堆划分多个区,跟踪每个区回收价值,维护优先列表  +  标记整理(减少碎片)

         初始标记---并发标记---最终标记--晒选回收

    其他:新生代的垃圾收集器有Serial(单线程)、

       ParNew(Serial的多线程版本)

      ParallelScavenge(吞吐量优先的垃圾收集器),

      老年代有SerialOld(单线程老年代)、

      ParallelOld(与ParallelScavenge搭配的多线程执行标记整理算法的老年代收集器)

 对象分配策略:.1.对象优先在Eden区分配

        2.大对象直接进入老年代

        3.长期存活的进入老年代

        4.Survivor区中相同年龄的所有对象大小的总和大于Survivor区空间的一半,

        年龄大于或等于该年龄的对象直接进入老年代

  

空间担保分配:在发生MinorGC(回收年轻代)之前,HandlePromotionFailure允许担保失败,

      老年代最大可用连续存储空间小于新生代所有对象总空间,且大于历次晋升到

      老年代对象的平均大小,进行一次MinorGC,若不满足条件,改为FUllGC(堆及永久代)

JDK命令:jps:列出正在运行虚拟机进程

       jstat:显示虚拟机进程中的类装载,内存,垃圾收集等数据。

       jinfo:查看调整各项参数  

       jmap:生成堆转储快照

原文地址:https://www.cnblogs.com/team42/p/7044926.html