【005】【JVM——Hotspot算法实现存活对象判定和垃圾收集】

Hotspot算法实现存活对象判断和垃圾收集

枚举根节点

作为GC Roots 的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(例如栈帧中的本地变量表)中,它们的数量庞大,逐个检查里面的引用,会消耗很多时间。其次,准确的可达性分析需要暂停用线程的执行。

目前的主流Java 虚拟机使用的都是准确式GC (准确式内存管理Exact Memory Management:虚拟机知道内存中某个位置的数据类型具体是什么),所以当执行系统停顿下米后, 并不需要一个不漏地检验所有执行上下文和全局的引用位置,虚拟机有办法直接得知哪些地方存放着对象引用。在HotSpot 的实现中, 使用一组称为OopMap 的数据结构来实现这个目的,在类加载完成的时候, HotSpot 就把对象内,什么偏移量上是什么类型的数据计算出来,在JIT 编译过程中,也会在特定的位置记录下战和号寄存器中哪些位置是引用。GC 在扫描时就可以直接知道这些信息了。

安全点

为每条指令都生成OopMap,消耗大量空间,GC成本很高。HotSpot也没有这样做,只在特定位记录这些信息,这些位置被称为“安全点”,即程序执行时并非所有地方都可以停下来开始GC,只有在到达安全点时才能暂停。安全点的选择是以程序“是否具有让程序长时间执行的特征”了标准进行选定的。最明显的就是指令复用,如方法调用,循环跳转。

如何让所有线程(不包括执行JNI 调用的线程)都“ 跑”到最近的安全点上再停顿下来。有两种方案抢先式中断( Preemptive Suspension )和主动式中断( Voluntary
Suspension )

  • 抢先式中断:不需要线程的执行代码主动去配合,在GC 发生时,首先把所有线程全部中断,如果发现有钱程中断的地方不在安全点上,就恢复线程,让它“跑”到安全点上. 现在几乎没有虚拟机实现。
  • 主动式中断:当GC需要中断线程的时候,不直接对线程操作,仅仅简单地设置一个标志,各个线程执行时主动去轮询这个标志,发现标志为真时就自己中断挂起。

轮询标志的地方和安全点是重合的,另外再加上创建对象需要分配内存的地方。

安全区域

命案点解决了如何进入GC 的问题,问题还是存在,如果线程处于睡眠状态或者阻塞状态,此时线程无法响应JVM的中断请求,不能“走”到安全的地方去中断挂起。 JVM 也不可能等待线程重新被分配CPU 时间。这样就需要要安全区域( Safe
Region )来解决。

安全区域:指在一段代码片段之中,引用关系不会发生变化。在这个区域中的任意地方开始GC 都是安全的,可以把安全区域看做是被扩展了的安全点。在线程执行到安全区域中的代码时,首先标识自己已经进入了安全区域,这段时间内JVM 发起GC,JVM不用管标识为安全区域状态的钱程了。线程离开安全区域时,它要检查系统是否已经完成了根节点枚举(或者是整个GC 过程),如果完成了,线程就继续执行,否则就必须等待直到收到可以安全离开安全区域的信号。

【参见】【深入理解Java虚拟机(第二版)】【周志明】

【首发】【http://my.oschina.net/shiinnny/blog/388432

时间: 2024-08-27 20:37:09

【005】【JVM——Hotspot算法实现存活对象判定和垃圾收集】的相关文章

JVM自动内存管理:对象判定和回收算法

可回收对象的判断方法 1.引用计数算法 2.可达性分析算法 引用计数算法 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象就是不可能再被使用的. 引用计数算法的缺陷:循环引用 可达性分析算法 可达性分析算法基本原理: 通过一些列的称为"GC Roots"的对象作为起始点,从这些节点开始进行向下搜索,搜索 所走过的路径成为引用链(Reference Chain),当一个对象到GC Roots没有任何引用连(用图论的

JVM 自动内存管理:对象判定和回收算法

【JVM】JVM垃圾收集器、垃圾收集算法、无用对象

Java 常见的垃圾收集器有哪些 实际上,垃圾收集器(GC,Garbage Collector)是和具体 JVM 实现紧密相关的,不同厂商(IBM.Oracle),不同版本的JVM,提供的选择也不同.接下来,我来谈谈最主流的 Oracle JDK. Serial GC 它是最古老的垃圾收集器,"Serial"体现在其收集工作是单线程的,并且在进 行垃圾收集过程中,会进入臭名昭著的"Stop-The-World"状态.当然,其单线程设计也意味着精简的 GC 实现,无需

JVM:Hotspot虚拟机中的对象

在HotSpot虚拟机中,对象在内存中存储的布局可以被分为3个区域:对象头(Header).实例数据(Instance data)和对齐填充(Padding).对象头包括两部分信息,第一部分存储自身的运行时数据,如哈希值.GC分代年龄.锁状态标志.线程持有的锁.偏向锁ID.偏向时间戳等,这部分数据的长度在32位和64位的虚拟机中(未开启压缩指针)分别为32bit和64bit,官方称它为 Mark Word. 存储内容 标志位 状态 对象哈希码.对象分代年龄 01 未锁定 指向锁记录的指针 00

Java虚拟机(三)垃圾标记算法与Java对象的生命周期

相关文章 Java虚拟机系列 前言 这一节我们来简单的介绍垃圾收集器,并学习垃圾标记的算法:引用计数算法和根搜索算法,为了更好的理解根搜索算法,会在文章的最后介绍Java对象在虚拟机中的生命周期. 1.垃圾收集器概述 垃圾收集器(Garbage Collection),通常被称作GC.提到GC,很多人认为它是伴随Java而出现的,其实GC出现的时间要比Java早太多了,它是1960诞生于MIT的Lisp. GC主要做了两个工作,一个是内存的划分和分配,一个是对垃圾进行回收.关于内存的划分和分配,

Java虚拟机 垃圾收集算法及HotSpot算法实现

垃圾收集算法 一般来说,垃圾收集算法分为四类: 标记-清除算法 最基础的算法便是标记-清除算法(Mark-Sweep).算法分为“标记”和“清除”两个阶段:首先标记处需要收集的对象,在标记完成之后,再统一回收所有被标记的对象. 这是最简单的一种算法,但是缺点也是很明显的:一个是效率问题,标记和清除效率都不高.二是空间问题,清除之后会产生大量的空间碎片,导致之后分配大对象找不到足够的连续对象而不得不触发另一次垃圾收集动作.算法执行过程如下图. 复制算法 复制算法(Copying)将可用内存按照容量

JVM回收算法

根搜索算法 原理:设立若干种根对象,当任何一个根对象到某一个对象均不可达时,则认为这个对象是可以被回收的.一般是对象持有的引用指向该对象不可达 在JAVA语言中,可以当做GC roots的对象有以下几种:          1.虚拟机栈中的引用的对象. 2.方法区中的类静态属性引用的对象. 3.方法区中的常量引用的对象. 4.本地方法栈中JNI的引用的对象. 第一和第四种都是指的方法的本地变量表,第二种表达的意思比较清晰,第三种主要指的是声明为final的常量值. 标记-清除算法 因为我们在程序

JVM GC算法 垃圾回收器

JVM的垃圾回收算法有三种: 1.标记-清除(mark-sweep):啥都不说,直接上图 2.标记-整理(mark-compact) 3.复制(copy) 分代收集算法                                                    目前的垃圾回收都采用分代收集算法.也就衍生了很多垃圾收集器 "分代收集"(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法. 在新生

STL算法设计理念 - 函数对象和函数对象当參数和返回值

函数对象: 重载函数调用操作符的类.其对象常称为函数对象(function object),即它们是行为类似函数的对象. 一个类对象,表现出一个函数的特征,就是通过"对象名+(參数列表)"的方式使用一个类对象,假设没有上下文,全然能够把它看作一个函数对待. 这是通过重载类的operator()来实现的. "在标准库中.函数对象被广泛地使用以获得弹性".标准库中的非常多算法都能够使用函数对象或者函数来作为自定的回调行为: demo #include <iostr