jvm-gc垃圾定位

357 阅读2分钟

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

JVM 一次完整的GC

1.新生代开始执行垃圾回收,堆中的Eden和其中一个Survivor区的存货对象放置到另一个Survivor区中,将这两个区清空。

2.如果Survivor区中放不下这么多对象,就会将多余的对象放置到老年代中(如果是大对象,就直接存放到老年代中)

3.Survivor中的对象每经过一次收集,幸存下来的对象年龄+1,当到达一定的年龄,就会晋升到老年代。(CMS 年龄6, Parallel年龄15)

什么是垃圾

  • 什么是垃圾?

没有任何引用指向的一个对象或者多个对象(循环引用);

如何定位垃圾

引用计数法

在对象添加一个引用计数器。当有一个地方引用,就+1,引用失效就-1,。当计数器为0时,代表不可能被使用。

缺点:有很多额外情况需要考虑,需要配合大量的额外处理才能使用。比如,两个对象循环依赖,就不可能回收

可达性分析

从“GC Roots”根对象作为起始节点集,从这些节点触发根据引用关系向下搜索,走过的路径为“引用链”。如果某个对象到起始节点没有任何引用链,说明这个对象不可能再被使用

  • 哪些对象可以作为GC Root根节点?
  • 虚拟机栈中引用的对象,比如当前正在运行的方法使用到的参数,局部变量,临时变量等。
  • 方法区中类静态属性引用的对象。 static String name = new String();
  • 方法区中常量引用的对象 final Integer i = new Integer();
  • 本地方法栈中JNI(native方法)引用的对象
  • 虚拟机内部的引用,如基本数据类型对应的Class对象,常驻的异常对象,NullPointException,系统类加载类。
  • 所有被同步锁持有的对象
  • 反应Java虚拟机内部情况的JMXBean。JVMTI中注册的回调,本地代码缓存等。

这些都可以放进GC Root根节点集合中,不仅这些,将一些关联区域的对象也一并加入。

局部回收,避免GC Roots包含过多的对象而多度膨胀。

如此看来,引用和对象存活 离不开关系