上篇文章中,我们了解了Java虚拟机垃圾回收的思路和策略,这篇文章我们将了解Java是如何实现高效的回收算法的。

  我们需要了解,内存回收必须要保证“一致性”,意思就是在执行GC分析的时候,系统看起来要像是冻结在某一时间点上,不能出现在分析过程中,引用的情况还在发生变化,这样就无法进行分析,这是为什么在GC时必须要停顿所有的Java线程(官方称之为Stop The World),Java是通过引用计数器和可达性分析算法来判断一个对象是否可以被回收的,在进行可达性分析的时候,首先要枚举出所有的根结点GC-Roots,一个一个去挑选显然是不现实的,因为这会导致系统长时间的STW,而且,虚拟机是可以知道哪些地方存在存放着直接引用的,依靠使用一种叫做OOP的数据结构来达到这个目的,在类加载完成的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译的过程中,也会在特定的位置几下栈和寄存器中哪些位置是引用,这样在GC扫描时,就可以直接获取这些信息了。

  上文也提到,并不会为每一条指令都创建OOP,因为这样会产生大量的内存消耗,得不偿失只会在特定位置创建,这个位置就是“安全点(Safe Point)”,程序只有在安全点才可以停下来执行GC,安全点设置的时候,为了追求合理(例如当需要执行GC时,不能让GC等候太久才进入安全点),这个标准就是“是否会让程序执行太久”,注意,这个判断条件不能以指令集的长度来判断,因为每条指令执行的时间都很短,其最明显的特征就是指令序列复用,例如方法跳转,循环跳转,异常跳转等,所以,具有这些功能的指令才会产生安全点。

  对于安全点,另一个需要考虑的问题是如何在GC发生时,让所有的线程都跑到最近的安全点上停下来,这里有两个方案选择:一是抢先式中断,就是在GC发生时,将所有的线程中断,如果发现有线程中断的地方不在安全点上,就恢复该线程,现在几乎没有虚拟机采用这种抢先式中断;而是主动式中断,设置一个标志,在GC发生时,该标志为真,在每个安全点上去查看这个标志,当这个标志为真时,就自己挂起中断。

  另外我们需要扩充一个安全域的概念,因为当有些线程正好处于Sleep或Block状态时,无法响应JVM的暂停请求,JVM也不可能等待CPU重新分配时间片,这就需要安全域来解决,安全域是指在一个代码片段中,引用关系不会发生变化,在这个区域中任何地方开始GC都是安全的,我们可以把安全域看作是对安全点的一个扩充。当线程执行到Safe Region时,就会标识自己已经进入SafeRegion,当需要执行GC时,不用管这种线程,当这种线程将要跳出SafeRegion时,会检查系统是否已经枚举完了根结点(或整个GC过程完成),如果没有,则必须等待到可以安全离开SafeRegion的信号为止。

  可以看出,JVM在具体的实现细节上遇到了很多问题,所以我们要深入了解JVM,学习优秀的解决方案,不能只停留在表面。

  本文我们了解了JVM在执行GC时的一些细节,下篇文章我们将会介绍几种流行的商用垃圾收集器。

深入理解JVM(六) -- GC执行原则和方案的更多相关文章

  1. 深入理解JVM+G1+GC.pdf (中文版带书签)

    目录 序 VII前言 IX 第1章 JVM & GC基础知识 11.1 引言 21.2 基本术语 31.2.1 Java相关术语 41.2.2 JVM/GC通用术语 241.2.3 G1涉及术 ...

  2. 深入理解JVM—字节码执行引擎

    原文地址:http://yhjhappy234.blog.163.com/blog/static/3163283220122204355694/ 前面我们不止一次的提到,Java是一种跨平台的语言,为 ...

  3. 深入理解JVM与GC回收

    JVM内存模型 java虚拟机在执行java程序的过程中会把它所管理的内存划分为不同的若干个不同的的数据区域,这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机的进程的启动而存在,有些区 ...

  4. 深入理解JVM(六)类文件结构

    6.1 关于类文件 1.class文件的一次编译,到处运行的跨平台性: 2.JVM不止有跨平台性,还有跨语言性,不管是JRuby还是Groovy写出来的程序,只要编译出符合JVM规范的class文件就 ...

  5. 深入理解JVM——虚拟机GC

    对象是否存活 Java的GC基于可达性分析算法(Python用引用计数法),通过可达性分析来判定对象是否存活.这个算法的基本思想是通过一系列"GC Roots"的对象作为起始点,从 ...

  6. Java 中级 学习笔记 1 JVM的理解以及新生代GC处理流程

    写在最前 从毕业到现在已经过去了差不多一年的时间,工作还算顺利,但总是离不开CRUD ,我觉得这样下去肯定是不行的,温水煮青蛙,势必有一天,会昏昏沉沉的迷失在温水里.所以,需要将之前学习JAVA 当中 ...

  7. 理解JVM GC

    理解JVM GC对于我们把控Java应用有很大的帮助.下面我从运维角度,把网上的JVM相关的资料整理如下,以加深对JVM GC的理解.如有错误的地方,请看官指正. JVM内存使用分类 JVM的内存分区 ...

  8. 深入理解JVM - 虚拟机字节码执行引 - 第八章

    概述从外观上看起来,所有的 Java 虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.主要从概念模型的角度来讲解虚拟机的方法调用和字节码执行. 运行时 ...

  9. jvm入门及理解(六)——垃圾回收与算法

    一.jvm垃圾回收要做的事情 哪些内存需要回收 什么时候回收 怎么回收 二.如何判断对象已经死亡,或者说确定为垃圾 引用计数法: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值就加1: ...

随机推荐

  1. compass和paoding分词器的基本使用

    1.实现搜索的技术: 数据库查询:like查询:lucene全文检索技术: 1)在数据量比较大,查询字段比较多的情况下,如果采用数据库like sql查询,性能比较差:采用lucene来查询,性能相对 ...

  2. 20189220 余超《Linux内核原理与分析》第四周作业

    构造一个简单的Linux系统MenuOS 第三章基础知识 计算机的三大法宝:存储计算机,函数调用堆栈,中断. 操作系统的两把宝剑:中断上下文,进程上下文. Linux内核源码的目录结构: arch目录 ...

  3. 反向传播BP算法

    前向传播模型 一般我们使用的公式是: \[ a=\frac{1}{1+\exp \left(-\left(w^{T} x+b\right)\right)} = \frac{1}{1+\exp \lef ...

  4. [代码质量] Git统计本次提交新增代码行数,建议每个评审commit新增行数小于400行

    git log HEAD~1..HEAD --author="$(git config --get user.name)" --pretty=tformat: --numstat ...

  5. Spring 事务模板方法设计模式

    接上一篇文章 上一篇讲到了doGetTransaction方法 一.模板方法设计模式 这里涉及到了一个经典的设计模式:模板方法 如下图: AbstractPlatformTransactionMana ...

  6. c++ 字符串时间格式转换为时间 判断有效期

    转载:https://www.cnblogs.com/maphc/p/3462952.html #include <iostream> #include <time.h> us ...

  7. 配置mongo.conf文件

    配置mongo.conf文件,优化mongod.exe的启动 在d:/Develop/MongoDB目录下创建mongo.conf文件并写入:   dbpath=d:\Develop\MongoDB\ ...

  8. osg::Node源码

    /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source ...

  9. PHP用curl抓取网站数据,仿造IP、伪造来源等,防屏蔽解决方案教程

    1.伪造客户端IP地址,伪造访问referer:(一般情况下这就可以访问到数据了) curl_setopt($curl, CURLOPT_HTTPHEADER, ['X-FORWARDED-FOR:1 ...

  10. 基于EasyNVR摄像机无插件直播方案二次开发实现自己的摄像机IPC-NVR无插件化直播解决方案

    背景介绍 在之前的博客中<基于EasyNVR实现RTSP/Onvif监控摄像头Web无插件化直播监控>,对EasyNVR所实现的功能我们已经有较多描述,这些也在方案地址:http://ww ...