OOM 分析 Java 堆内存溢出 在 Java 堆中只要不断的创建对象,并且 GC-Roots 到对象之间存在引用链,这样 JVM 就不会回收对象。 ArrayList<>(10) ; while (true){ list.add("1") ; } } 当出现 OOM 时可以通过工具来分析 GC-Roots 引用链 ,查看对象和 GC-Roots 是如何进行关联的,是否存在对象的生命周期过长,或者是这些对象确实改存在的,那就要考虑将堆内存调大了。
CMS 回收的过程可以划分为七个步骤,下面我们就来详细介绍: 初始标记 并发标记 并发预清理 可中断的并发预清理 重新标记 并发清除 并发重置 4.1 初始标记 如上所述,初始标记最重要的工作就是以 GC-Roots 但是,除了被 GC-Root 引用外,老年代中的对象如果仅被年轻代中的对象引用,他也是不能回收的,因此,在上述以 GC-Roots 为起点进行的标记完成后,还需要遍历新生代对象,标记可达的老年代对象。 由于上述两个过程仅仅遍历被 GC-Roots 和新生代对象直接引用的老年代对象,执行起来速度会非常快,为了避免在标记过程中对象引用的动态变化,在初始标记阶段,程序需要进行短暂停止,这称为“Stop The 初始标记的过程中,为了尽量缩短用户线程的暂停时间,所以仅对被 GC-Roots 和新生代对象直接引用的老年代对象进行了标记,所以,接下来的一项工作就是对 GC-Roots 和新生代对象间接引用的老年代对象进行标记
运行程序把所有的引用关系链看作一张图,通过GC-Roots根对象对象集合作为起始点,从每个根节点向下不断搜索被根对象集合所连接的对象是否可达,搜索路径称为引用链(Reference-Chain),如果对象到 GC-Roots没有任何引用链存在,则说明此对象是不可用的, 虚拟机栈中引用的对象; 元空间中类静态属性引用的对象; 元空间中常量引用的对象; 本地方法栈中Native方法引用的对象; 相对于引用计数法算法
垃圾对象标记 可达性分析算法是基于对象到根对象的引用链是否可达来判断对象是否可以被回收; 运行程序把所有的引用关系链看作一张图,通过GC-Roots根对象对象集合作为起始点,从每个根节点向下不断搜索被根对象集合所连接的对象是否可达 ,搜索路径称为引用链(Reference-Chain),如果对象到GC-Roots没有任何引用链存在,则说明此对象是不可用的,虚拟机栈中引用的对象如下: 元空间中类静态属性引用的对象; 元空间中常量引用的对象
Paste_Image.png 从图中可以看出,object5、object6、object7 对象是没有GC-Roots 引用(间接引用),因此,这三个对象可以被垃圾收集器回收。
Reference Counting 引用计数法 (如果 Object 的 Reference-Counting =0;那么这个Object 不会被用到,即可回收) GC Roots 可达性分析 (如果 GC-Roots
当判断对象不存在引用时,会执行清理动作; 完成对象清理后会重新整理内存空间; 这里存在一个很难理解的概念,即对象不存在引用的判断,也就是常说的可达性分析算法:基于对象到根对象的引用链是否可达来判断对象是否可以被回收;GC-Roots
GC的回收算法 (1) 标记-清除算法,缺点是容易产生碎片,且效率不高,标记过程和清除过程效率都不高 标记-清除算法的过程,分为两个过程,标记过程和清除过程 ① 标记过程,遍历所有的GC-roots ,然后将所有GC-roots可达的对象标记为存活的对象(记为1) ② 清除过程,遍历堆中的所有对象,将没有标记的对象全部清除掉(没有标记过的,记为0) ③ 清除过后,被标记过的对象留下, STAB(snapshot-at-the-beginning)形式的并发标记,标记完成后,G1知道哪个区域是空的,它首先会收集那些产生大量空闲空间的区域 ii.初始标记STW:耗时很短,标记GC-roots
可以用作 GC-Roots 的对象有: 方法区中静态变量所引用的对象。 虚拟机栈中所引用的对象。
此算法用于新生代内存回收,从E区回收到S0或者S1 从根集合扫描、就是刚才说的GC-Roots 收集算法、从它开始查你的引用、如果没有被引用、开始执行算法、并将存活对象复制到一块新的、(S0或者S1)
算法的基本思路是通过一些称为“GC-Roots”的对象,从这些节点往下延伸,搜索所走过的路叫引用链,当一个对象没有被引用链搜索到,则证明该对象不可用。 如下图Object-5\6\7是不可用的: 可用作GC-Roots的对象有: 1.方法区的静态类型引用的对象 2.方法区的常量引用的对象 3.方法栈中引用 10. 垃圾收集的方法有哪些?