你知道JVM中GC Root对象有哪些吗

目录
  • JVM中GC Root对象有哪些
    • (一)虚拟机栈中引用的对象
    • (二)方法区中类静态属性引用的对象
    • (三)方法区中常量引用的对象
    • (四)本地方法栈中引用的对象
  • JVM 中的 GC Roots 和可达链
    • 什么是GC Root 对象?
    • 常用的GC算法
    • GC Root 对象有哪些?
  • 总结

JVM中GC Root对象有哪些

众所周知,我们目前最常用的虚拟机hotspot使用可达性分析来进行垃圾回收,而可达性分析需要依赖GC Root。

下面我就来介绍下可以作为GC Root的对象。

(一)虚拟机栈中引用的对象

虚拟机栈中的引用的对象可以作为GC Root。我们程序在虚拟机的栈中执行,每次函数调用调用都是一次入栈。在栈中包括局部变量表和操作数栈,局部变量表中的变量可能为引用类型(reference),他们引用的对象即可作为GC Root。不过随着函数调用结束出栈,这些引用便会消失。

(二)方法区中类静态属性引用的对象

简单的说就是我们在类中使用的static声明的引用类型字段,例如:

Class Dog {
    private static Object tail;
} 

(三)方法区中常量引用的对象

简单的说就是我们在类中使用final声明的引用类型字段,例如:

Class Dog {
    private final Object tail;
} 

(四)本地方法栈中引用的对象

就是程序中native本地方法引用的对象。

JVM 中的 GC Roots 和可达链

什么是GC Root 对象?

简单讲,凡是被常量、静态变量、全局变量、运行时方法中的变量直接引用的对象,原则上不能被GC释放。

JVM中对内存进行回收时,需要判断对象是否仍在使用中,可以通过 GC Roots Tracing辨别。

GC Roots 定义:

通过一系列名为”GCRoots”的对象作为起始点,从这个节点向下搜索,搜索走过的路径称为ReferenceChain,当一个对象到GCRoots没有任何ReferenceChain相连时,(图论:这个对象不可到达),则证明这个对象不可用。

可以作为GC Root 引用点的是:

  • JavaStack中的引用的对象。
  • 方法区中静态引用指向的对象。
  • 方法区中常量引用指向的对象。
  • Native方法中JNI引用的对象。

所谓“GC roots”,或者说tracing GC的“根集合”,就是一组必须活跃的引用。

Tracing GC的根本思路就是:给定一个集合的引用作为根出发,通过引用关系遍历对象图,能被遍历到的(可到达的)对象就被判定为存活,其余对象(也就是没有被遍历到的)就自然被判定为死亡。注意再注意:tracing GC的本质是通过找出所有活对象来把其余空间认定为“无用”,而不是找出所有死掉的对象并回收它们占用的空间。

GC roots这组引用是tracing GC的起点。要实现语义正确的tracing GC,就必须要能完整枚举出所有的GC roots,否则就可能会漏扫描应该存活的对象,导致GC错误回收了这些被漏扫的活对象。

这就像任何递归定义的关系一样,如果只定义了递推项而不定义初始项的话,关系就无法成立——无从开始;而如果初始项定义漏了内容的话,递推出去也会漏内容。

常说的GC(Garbage Collector) roots,特指的是垃圾收集器(Garbage Collector)的对象,GC会收集那些不是GC roots且没有被GC roots引用的对象。

Java 进行GC的时候会从GC root进行可达性判断,常见的GC Root有如下:

  • 通过System Class Loader或者Boot Class Loader加载的class对象(通过自定义类加载器加载的class不一定是GC Root)
  • 处于激活状态的线程
  • 栈中的对象
  • JNI栈中的对象
  • JNI中的全局对象
  • 正在被用于同步的各种锁对象
  • JVM自身持有的对象,比如系统类加载器等。

在调查内存泄漏原因的时候可以根据GC Root来推导.

常用的GC算法

了解了这些,我们来看一下常用的GC算法

标记回收算法

从GC root进行遍历,把可达对象都标记,剩下那些不可达的进行回收,这种方式需要中断其他线程,并且可能产生内存碎片

复制算法

把内存区域分为两块,每次使用一块,GC的时候把一块中的内容移动到另一块中,原始内存中的对象就可以被回收了。

标记压缩算法

和标记回收差不多,但是在回收的时候会对可达对象进行整理,将其压缩到内存的一段,避免内存碎片

分代算法

将内存区域分代,对不同的代使用不同的回收算法,通常分为新生代,老年代,和永久带。

新生代一般包含三个区域,Eden区和两个Survivor区,新生代一般采用复制算法

老年代一般采用标记压缩算法.

GC Root 对象有哪些?

JVM垃圾回收的根对象的范围有以下几种:

(1)虚拟机(JVM)栈中引用对象

(2)方法区中的类静态属性引用对象

(3)方法区中常量引用的对象(final 的常量值)

(4)本地方法栈JNI的引用对象

一个对象可以属于多个root,GC root有几下种:

  • Class由系统类加载器(system class loader)加载的对象,这些类是不能够被回收的,他们可以以静态字段的方式保存持有其它对象。我们需要注意的一点就是,通过用户自定义的类加载器加载的类,除非相应的java.lang.Class实例以其它的某种(或多种)方式成为roots,否则它们并不是roots,.
  • Thread活着的线程
  • Stack Local Java方法的local变量或参数
  • JNI Local JNI方法的local变量或参数
  • JNI Global 全局JNI引用
  • Monitor Used 用于同步的监控对象
  • Held by JVM 用于JVM特殊目的由GC保留的对象,但实际上这个与JVM的实现是有关的。可能已知的一些类型是:系统类加载器、一些JVM知道的重要的异常类、一些用于处理异常的预分配对象以及一些自定义的类加载器等。然而,JVM并没有为这些对象提供其它的信息,因此就只有留给分析分员去确定哪些是属于"JVM持有"的了。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 教你JVM怎么使用native memory

    目录 JRE如何使用native存储 Java堆和GC The Just-in-time (JIT) compiler Classes and classloaders JNI NIO Threads JRE如何使用native存储 今天看到一篇特别好的文章,翻译其中一小段Understanding how the JVM uses native memory Runtime环境提供了被某些未知的用户代码驱动的能力,这使runtime在任何情况下都能使用合适的资源.每一个JVM管理的java应用

  • JVM类加载器之ClassLoader的使用详解

    目录 类加载器 概述 加载器的种类 验证不同加载器 核心方法 JVM类加载机制的三种方式 全盘负责 父类委托.双亲委派 缓存机制 打破双亲委派 重写loadclass方法 自定义类加载器 准备字节码文件 创建自定义类加载器 执行测试 注意事项 类加载器 概述 类加载器负责读取Java字节代码,并转换成java.lang.Class类的一个实例的代码模块. 类加载器除了用于加载类外,还可用于确定类在Java虚拟机中的唯一性. 任意一个类,都由加载它的类加载器和这个类本身一同确定其在 Java 虚拟

  • 从 JVM 中深入探究 Synchronized作用及原理

    目录 开篇语 Synchronized 使用 synchronized 实现原理 对象头 字节序 Java 中的字节序 如何阅读对象头 偏向锁 获取偏向锁 释放偏向锁 偏向撤销 批量重偏向 批量撤销偏向 Hashcode 去哪了 Lock Record 场景 1 场景2 轻量级锁 获取轻量级锁 加锁过程 释放轻量级锁 重量级锁 获取重量级锁 膨胀过程 竞争锁过程 释放重量级锁 释放锁过程 wait(),notify(),notifyAll() 开篇语 Synchronized,Java 友好的提

  • Native Memory Tracking追踪区域示例分析

    目录 Compiler Internal Symbol Native Memory Tracking Arena Chunk Unknown Compiler Compiler 就是 JIT 编译器线程在编译 code 时本身所使用的内存. 查看 NMT 详情: [0x0000ffff93e3acc0] Thread::allocate(unsigned long, bool, MemoryType)+0x348 [0x0000ffff9377a498] CompileBroker::make_

  • JVM调优OutOfMemoryError异常分析

    目录 1.Java 堆溢出 1.1 设置JVM参数 1.2 测试代码 1.3 运行OOM日志 2.Java栈.本地方法栈溢出 2.1 设置JVM参数 2.2 测试代码 2.3 运行OOM日志 2.4 Java虚拟机OOM异常 3.Java 运行常量池溢出 3.1 设置JVM参数-注意区分jdk版本 3.2 测试代码 3.3 运行OOM日志 4.Java 方法区溢出-jdk8 4.1 设置JVM参数 4.2 测试代码 4.3 运行OOM日志 5.本机直接内存溢出 5.1 设置JVM参数 5.2 测

  • 你知道JVM中GC Root对象有哪些吗

    目录 JVM中GC Root对象有哪些 (一)虚拟机栈中引用的对象 (二)方法区中类静态属性引用的对象 (三)方法区中常量引用的对象 (四)本地方法栈中引用的对象 JVM 中的 GC Roots 和可达链 什么是GC Root 对象? 常用的GC算法 GC Root 对象有哪些? 总结 JVM中GC Root对象有哪些 众所周知,我们目前最常用的虚拟机hotspot使用可达性分析来进行垃圾回收,而可达性分析需要依赖GC Root. 下面我就来介绍下可以作为GC Root的对象. (一)虚拟机栈中

  • java基础学习JVM中GC的算法

    在java学习到JVM时候,总会很多朋友问到关于GC算法的问题,小编在此给大家整理关于JVM中GC算法的原理以及图文详细分析,希望能够帮助你对这个GC算法的理解. JVM内存组成结构: (1)堆 所有通过new创建的对象都是在堆中分配内存,其大小可以通过-Xmx和-Xms来控制,堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区.Survivor被划分为from space 和 to space组成,结构图如下: (2)栈 每个线程 执行每个方法的时候都会在栈中申请一个

  • JVM中判定对象需要回收的方法

    引用计数法 每个对象上都有一个引用计数,对象每被引用一次,引用计数器就+1,对象引用被释放,引用计数器-1,直到对象的引用计数为0,对象就标识可以回收 这个可以用数据算法中的图形表示,对象A-对象B-对象C 都有引用,所以不会被回收,对象B由于没有被引用,没有路径可以达到对象B,对象B的引用计数就就是0,对象B就会被回收. 但是这个算法有明显的缺陷,对于循环引用的情况下,循环引用的对象就不会被回收.例如下图:对象A,对象B 循环引用,没有其他的对象引用A和B,则A和B 都不会被回收. root搜

  • 浅谈jvm中的垃圾回收策略

    java和C#中的内存的分配和释放都是由虚拟机自动管理的,此前我已经介绍了CLR中GC的对象回收方式,是基于代的内存回收策略,其实在java中,JVM的对象回收策略也是基于分代的思想.这样做的目的就是为了提高垃圾 回收的性能,避免对堆中的所有对象进行检查时所带来的程序的响应的延迟,因为jvm执行GC时,会stop the word,即终止其它线程的运行,等回收完毕,才恢复其它线程的操作.基于分代的思想是:jvm在每一次执行垃圾收集器时,只是对一小部分内存 对象引用进行检查,这一小部分对象的生命周

  • 详解JVM中的GC调优

    那些GC的默认值 其实GC或者说JVM的参数非常非常的多,有控制内存使用的: 有控制JIT的: 有控制分代比例的,也有控制GC并发的: 当然,大部分的参数其实并不需要我们自行去调整,JVM会很好的动态帮我们设置这些变量的值. 如果我们不去设置这些值,那么对GC性能比较有影响的参数和他们的默认值有哪些呢? GC的选择 我们知道JVM中的GC有很多种,不同的GC选择对java程序的性能影响还是比较大的. 在JDK9之后,G1已经是默认的垃圾回收器了. 我们看一下G1的调优参数. G1是基于分代技术的

  • JVM中四种GC算法案例详解

    目录 介绍 引用计数算法(Reference counting) 算法思想: 核心思想: 优点: 缺点: 例子如图: 标记–清除算法(Mark-Sweep) 算法思想: 优点 缺点 例子如图 标记–整理算法 算法思想 优点 缺点 例子 复制算法 算法思想 优点 缺点 总结 介绍 程序在运行过程中,会产生大量的内存垃圾(一些没有引用指向的内存对象都属于内存垃圾,因为这些对象已经无法访问,程序用不了它们了,对程序而言它们已经死亡),为了确保程序运行时的性能,java虚拟机在程序运行的过程中不断地进行

  • JVM中对象的创建与OOP-Klass模型

    目录 JVM中OOP-KLASS模型 JVM中,使用了OOP-KLASS模型来表示java对象 instanceOopDesc,只包含数据信息,它包含三部分 实例说明 JVM中OOP-KLASS模型 JVM中,使用了OOP-KLASS模型来表示java对象 即: 1.jvm在加载class时,会创建instanceKlass,表示其元数据,包括常量池.字段.方法等,存放在方法区:instanceKlass是jvm中的数据结构: 2.在new一个对象时,jvm创建instanceOopDesc,来

  • JVM中的GC初识

    目录 GC简介 何为GC 为何要学习GC GC垃圾对象判定 引用计数法 可达性分析法 常见GC算法分析 标记清除 标记复制 标记整理 分代回收 章节面试分析 GC简介 何为GC GC(Garbage Collection)称之为垃圾回收,是对内存中的垃圾对象,采用一定的算法进行内存回收的一个动作.比方说,java中的垃圾回收会对内存中的对象进行遍历,对存活的对象进行标记,其未标记对象可认为是垃圾对象,然后基于特定算法进行回收. 为何要学习GC 深入理解GC的工作机制,可以帮你写出更好的Java应

  • Java 对象在 JVM 中的内存布局超详细解说

    目录 一.new 对象的几种说法 二.Java 对象在内存中的存在形式 1. 栈帧(Frame) 2. 对象在内存中的存在形式 ① 3. 对象中的方法存储在那儿? 4. Java 对象在内存中的存在形式 ② 三.类中属性详细说明 四.细小知识点 1. 如何创建对象 2. 如何访问属性 五.Exercise 六.总结 一.new 对象的几种说法 初学 Java 面向对象的时候,实例化对象的说法有很多种,我老是被这些说法给弄晕. public class Test { public static v

  • Java对象在JVM中的生命周期详解

    概念 在Java中,对象的生命周期包括以下几个阶段: 创建阶段(Created) 应用阶段(In Use) 不可见阶段(Invisible) 不可达阶段(Unreachable) 收集阶段(Collected) 终结阶段(Finalized) 对象空间重分配阶段(De-allocated) Java对象在JVM中的生命周期 当你通过new语句创建一个java对象时,JVM就会为这个对象分配一块内存空间,只要这个对象被引用变量引用了,那么这个对象就会一直驻留在内存中,否则,它就会结束生命周期,JV

随机推荐