JVM执行引擎和垃圾回收要点总结

目录
  • 一、执行引擎
  • 二、垃圾对象标记
    • 1、引用计数法
    • 2、可达性分析算法
  • 三、垃圾回收机制
    • 1、标记清除算法
    • 2、标记整理算法
    • 3、复制算法
    • 4、分代收集算法
  • 四、源代码地址

一、执行引擎

应用程序经过编译,转换为字节码文件,字节码加载到内存空间并不能直接在操作系统上执行,执行引擎作为Java虚拟机核心的组成部分,作用就是将字节码指令解释/编译为对应系统平台上的本地机器指令。

解释器:虚拟机启动时会根据预定义对字节码采用逐行解释的方式执行,将每条字节码文件中的内容解释为对应系统平台的本地机器指令执行;

JIT编译器:虚拟机将源代码编译成本地机器平台相关的机器语言,并且寻找热点高频执行的代码将其放入元空间中,即元空间中存放的JIT缓存代码;

垃圾回收:对于没有任何引用的对象标记为垃圾,会被回收释放内存空间。

二、垃圾对象标记

1、引用计数法

每个对象保存一个整型引用计数器,用来记录对象被引用的次数,当该对象被一个对象引用时,计数器加1,当失去一个引用时,计数器减1;引用计数算法就是通过判断对象的引用数量来决定对象是否可以被当做垃圾对象回收掉。

虽然引用计数法效率高,但是当两个对象互相引用时会导致这两个对象一直不会被回收,这是一个致命的缺陷。所以JVM并没有采用该标记算法。

2、可达性分析算法

可达性分析算法是基于对象到根对象的引用链是否可达来判断对象是否可以被回收;

运行程序把所有的引用关系链看作一张图,通过GC-Roots根对象对象集合作为起始点,从每个根节点向下不断搜索被根对象集合所连接的对象是否可达,搜索路径称为引用链(Reference-Chain),如果对象到GC-Roots没有任何引用链存在,则说明此对象是不可用的,

  • 虚拟机栈中引用的对象;
  • 元空间中类静态属性引用的对象;
  • 元空间中常量引用的对象;
  • 本地方法栈中Native方法引用的对象;

相对于引用计数法算法,可达性分析算法则避免了循环引用导致的问题,同样具备执行高效的特点,也是JVM采用的标记算法。

三、垃圾回收机制

1、标记清除算法

标记-清除算法分为标记和清除两个阶段:

标记阶段:从根对象集合进行扫描,对存活的对象对象标记;清除阶段:再次扫描发现未被标记的对象并进行回收;

该算法效率不高,进行垃圾回收需要暂停应用程序,同时会产生大量内存碎片,后续程序运行过程中分配内存占用较大的对象时,会有连续内存不够情况,容易触发再一次垃圾收集动作。

2、标记整理算法

标记整理算法的标记过程类似标记清除算法,第一阶段:标记出垃圾对象;第二阶段:让所有存活的对象都向内存区一端移动;第三阶段:直接清理掉边界端以外的内存,类似于磁盘整理的过程;

该垃圾回收算法效率不高,对象移动过程需要暂停应用程序,适用于对象存活率高的场景(老年代)。

3、复制算法

复制算法将内存按容量划分为大小相等的两块,每次只使用其中的一块,当使用的这块的内存用完,就将还存活着的对象复制到另外一块空闲内存上,然后使用过的内存空间一次清理。

该算法实现简单,运行效率高,但是内存空间严重浪费,适用于对象存活率低的场景,比如新生代。

4、分代收集算法

当前市场上几乎所有的虚拟机都采用该回收算法,分代收集算法根据年轻代和老年代的各自特点采用不同的算法机制,不同内存区域中对象生命周期也不同,因此对堆内存不同区域采用不同的回收策略可以提高垃圾回收执行效率。通常情况新生代对象存活率低,回收频繁,就采用复制算法;老年代存对象生命周期长,活率高,就用标记清除算法或者标记整理算法。

Java堆内存一般可以分为新生代、老年代和永久代三个模块,如下图所示:

新生代

通常情况下,新创建的对象实例首先都是放在新生代空间中,所以追求快速的回收掉垃圾对象,一般情况下,新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区,对象实例大部分在Eden区中生成;

垃圾回收时先把eden区存活对象复制到S0区,然后清空eden区,当S0区也满时,再将eden区和S0区存活对象复制到S1区,然后清空eden和S0区,之后交换S0区和S1区的角色,当S1区无法存放eden区和S0区的存活对象时,就将存活对象直接存移到老年代区,当老年代区也满了,触发一次FullGC,即新生代、老年代都进行回收。

老年代

老年代区存放一些生命周期较长的对象,对象实例在新生代中经历了多次垃圾回收仍然存活的对象,会被移动到老年代区中。

四、源代码地址

GitHub·地址
https://github.com/cicadasmile/java-base-parent
GitEE·地址
https://gitee.com/cicadasmile/java-base-parent

以上就是JVM执行引擎和垃圾回收要点总结的详细内容,更多关于JVM执行引擎和垃圾回收的资料请关注我们其它相关文章!

(0)

相关推荐

  • 浅谈JVM垃圾回收之哪些对象可以被回收

    1.背景 Java语言相比于C和C++,一个最大的特点就是不需要程序员自己手动去申请和释放内存,这一切交由JVM来完成.在Java中,运行时的数据区域分为程序计数器.Java虚拟机栈.本地方法栈.方法区和堆.其中,程序计数器.虚拟机栈和本地方法栈是线程私有的,线程销毁后自动释放.垃圾回收的行为发生在堆和方法区,主要是堆,而堆中存储的主要是对象.那么自然而然地就会有这么几个问题,哪些对象可以被回收?通过什么方式回收?本文主要探讨第一个问题,以及JVM对Java中几种引用的回收策略. 2.如何判断一

  • JVM垃圾回收算法的概念与分析

    前言 在JVM内存模型中会将堆内存划分新生代.老年代两个区域,两块区域的主要区别在于新生代存放存活时间较短的对象,老年代存放存活时间较久的对象,除了存活时间不同外,还有垃圾回收策略的不同,在JVM中中有以下回收算法: 标记清除 标记整理 复制算法 分代收集算法 有了垃圾回收算法,那JVM是如果确定对象是垃圾对象的呢?判断对象是否存活JVM也会有几套自己判断算法了: 引用记数 可达性分析 有了垃圾回收和判断对象存在这两个概念后,再来逐步分析它们. JVM是如何判断对象是否存活的? 要是让开发人员来

  • JVM的垃圾回收算法工作原理详解

    怎么判断对象是否可以被回收? 共有2种方法,引用计数法和可达性分析 1.引用计数法 所谓引用计数法就是给每一个对象设置一个引用计数器,每当有一个地方引用这个对象时,就将计数器加一,引用失效时,计数器就减一.当一个对象的引用计数器为零时,说明此对象没有被引用,也就是"死对象",将会被垃圾回收. 引用计数法有一个缺陷就是无法解决循环引用问题,也就是说当对象A引用对象B,对象B又引用者对象A,那么此时A,B对象的引用计数器都不为零,也就造成无法完成垃圾回收,所以主流的虚拟机都没有采用这种算法

  • 快速理解Java垃圾回收和jvm中的stw

    Java中Stop-The-World机制简称STW,是在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外).Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互:这些现象多半是由于gc引起. GC时的Stop the World(STW)是大家最大的敌人.但可能很多人还不清楚,除了GC,JVM下还会发生停顿现象. JVM里有一条特殊的线程--VM Threads,专门用来执行一些特殊的VM Operation

  • JVM教程之内存管理和垃圾回收(三)

    JVM内存组成结构 JVM栈由堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)堆 所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制.堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由From Space和To Space组成,结构图如下所示: 新生代.新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代大小可以由-Xmn来控制,也可以用-XX:Surv

  • JVM垃圾回收原理解析

    概述 Java运行时区域中,程序计数器,虚拟机栈,本地方法栈三个区域随着线程的而生,随线程而死,这几个区域的内存分配和回收都具备确定性,不需要过多考虑回收问题.而Java堆和方法区则不一样,一个接口的多个实现类需要的内存不一样,一个方法的多个分支需要的内存可能也不一眼,我们只有在运行期,才能知道会创建的对象,这部分的内存分配和回收,是垃圾回收器所关注的.垃圾回收器需要完成三个问题:那些内存需要回收:什么时候回收以及如何回收. 那些垃圾需要回收 垃圾回收的基本思想是考察一个对象的可达性,即从根节点

  • JVM的7种垃圾回收器(小结)

    垃圾回收算法和垃圾回收器 对于JVM的垃圾回收算法有复制算法.标记清除.标记整理. 用阳哥的话就是:这些算法只是天上飞的理念,是一种方法论,但是真正的垃圾回收还需要有落地实现,所以垃圾回收器应运而生. JVM回收的区域包括方法区和堆,jvm对于不同区域不同的特点采用分代收集算法,比如因为所有的对象都是在Eden区进行分配,并且大部分对象的存活时间都不长,都是"朝生夕死"的,每次新生代存活的对象都不多,所以新采取复制算法:而jvm默认是新生代的对象熬过15次GC才能进入老年代,所以老年代

  • 详解Java内存管理中的JVM垃圾回收

    一.概述 相比起C和C++的自己回收内存,JAVA要方便得多,因为JVM会为我们自动分配内存以及回收内存. 在之前的JVM 之内存管理 中,我们介绍了JVM内存管理的几个区域,其中程序计数器以及虚拟机栈是线程私有的,随线程而灭,故而它是不用考虑垃圾回收的,因为线程结束其内存空间即释放. 而JAVA堆和方法区则不一样,JAVA堆和方法区时存放的是对象的实例信息以及对象的其他信息,这部分是垃圾回收的主要地点. 二.JAVA堆垃圾回收 垃圾回收主要考虑的问题有两个:一个是效率问题,一个是空间碎片问题.

  • 浅析JVM的垃圾回收器

    JVM的GC经过多年的发展,大家对Minor GC.major GC的理解并不完全一致,所以我不打算在本文中使用这个概念.我把GC大概分为一下4类: Young GC:只是负责回收年轻代对象的GC: Old GC:只是负责回收老年代对象的GC: Full GC:回收整个堆的对象,包括年轻代.老年代.持久带: Mixed GC:回收年轻代和部分老年代的GC (G1): 因为笔者目前使用G1还是比较少的,所以本文不打算将G1. 垃圾回收器算法 目前主流垃圾回收器都采用的是可达性分析算法来判断对象是否

  • JVM执行引擎和垃圾回收要点总结

    目录 一.执行引擎 二.垃圾对象标记 1.引用计数法 2.可达性分析算法 三.垃圾回收机制 1.标记清除算法 2.标记整理算法 3.复制算法 4.分代收集算法 四.源代码地址 一.执行引擎 应用程序经过编译,转换为字节码文件,字节码加载到内存空间并不能直接在操作系统上执行,执行引擎作为Java虚拟机核心的组成部分,作用就是将字节码指令解释/编译为对应系统平台上的本地机器指令. 解释器:虚拟机启动时会根据预定义对字节码采用逐行解释的方式执行,将每条字节码文件中的内容解释为对应系统平台的本地机器指令

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

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

  • jvm垃圾回收算法详细解析

    目录 前言 几种常用的垃圾回收算法 1.引用计数法 2.根搜索算法 3.标记清除法(Mark-Sweep) 4.复制交换算法(Mark-Sweep) 5.标记压缩算法(Mark-Compact) JVM 分代收集算法 前言 相比C语言,JVM虚拟机一个优势体现在对对象的垃圾回收上,JVM有一套完整的垃圾回收算法,可以对程序运行时产生的垃圾对象进行及时的回收,以便释放JVM相应区域的内存空间,确保程序稳定高效的运行,但在真正了解垃圾回收算法之前,有必要对JVM的对象的引用做一个简单的铺垫 JVM对

  • Java 垃圾回收机制详解(动力节点Java学院整理)

    1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的一个系统级线程会自动释放该内存块.垃圾回收意味着程序不再需要的对象是"无用信息",这些信息将被丢弃.当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用.事实上,除了释放没用的对象,垃圾回收也可以清除内存记录碎片.由于创建对象和垃圾回收器释放丢弃对象所占的内存空间,

  • 详解JavaScript的垃圾回收机制

    目录 为什么需要垃圾回收(GC) 什么是垃圾回收 垃圾产生 垃圾回收策略 引用计数标记 循环引用引发的问题 解决方法 引用计数算法的优缺点 标记清除算法 核心思想 标记清除算法优缺点 标记整理算法 V8引擎的垃圾回收 回收新生代对象 对象晋升机制 回收老生代对象 参考文档: 总结 为什么需要垃圾回收(GC) 程序和人一样,生活时间长了会产生垃圾,程序在运行过程中也会产生垃圾,垃圾积攒过多后,会导致程序运行速度变慢. 在JavaScript中的字符串.对象.数组等数据的内存是不固定的,只有真正使用

  • 一文带你了解JavaScript垃圾回收机制

    目录 1. 概述 2. 内存管理 3. 垃圾回收 4. GC算法介绍 5. 引用计数算法 1. 引用计数优缺点 6. 标记清除算法 1. 标记清除算法优缺点 7. 标记整理算法 8. 执行时机 9. V8引擎 1. 垃圾回收策略 2. 回收新生代对象 3. 回收老生代对象 4. V8垃圾回收总结 10. Performance工具介绍 1. 内存问题的体现 2. 监控内存的几种方式 3. 任务管理器监控内存 4. TimeLine记录内容 5. 堆快照查找分离DOM 6. 判断是否存在频繁GC

  • php中session垃圾回收机制

    在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾.PHP会将其在内存中销毁:这是PHP的GC垃圾处理机制,防止内存溢出. GC的工作就是扫描所有的Session信息,用当前时间减去session最后修改的时间,同session.gc_maxlifetime参数进行比较,如果生存时间超过gc_maxlifetime(默认24分钟),就将该session删除. 当一个有效的请求发生时,PHP 会根据全局变量 session.gc_probability和session.gc_divisor

  • 谈谈.net对象生命周期(垃圾回收)

    不用程序员操心的堆 -托管堆 程序在计算机上跑着,就难免会占用内存资源来存储在程序运行过程中的数据,我们按照内存资源的存取方式将内存划分为堆内存和栈内存. 栈内存,通常使用的场景是:对存取速度要求较高且数据量不大. 典型的栈内存使用的例子就是函数栈,每一个函数被调用时都会被分配一块内存,这块内存被称为栈内存,以先进后出的方式存取数据,在函数执行过程中不断往函数栈中压入(PUSH)数据(值类型数据:int.float.对象的引用...),函数执行完后又将函数栈中的数据逐个弹出(POP),由于是以操

  • Java虚拟机执行引擎知识总结

    执行引擎 也只有几个概念, JVM方法调用和执行的基础数据结构是 栈帧, 是内存区域中 虚拟机栈中的栈元素, 每一个方法的执行就对应着一个栈帧在虚拟机栈中出栈入栈的过程. 栈帧:则是包含有局部变量表, 操作数栈, 动态连接, 方法返回地址, 附加信息. 1 局部变量表: 存储单位是 slot, 一个slot占据32位, 对于64位的数据类型, 则是分配连续两个slot空间. 而对于一个非静态方法而言, 有一个隐藏参数, 为 this, 而在局部变量表中的变量存储顺序则是 this -> 方法参数

  • JVM类加载,垃圾回收

    目录 类加载子系统 双亲委派模型 垃圾回收 判断对象已死 JDK1.2之后的四种引用类型: 1.强引用: 2.软引用: 3.弱引用: 4.虚引用: 常见的垃圾回收算法: 1.标记–清除算法:(Mark–Sweep) 2.标记–复制算法: 3.标记–整理算法: 常见的垃圾回收器: 新时代.老年代 为什么大对象会直接存在老年代? 总结 类加载子系统 classLoader 只负责对字节码文件的加载,至于是否可以运行,还要看执行引擎. 加载的类信息存放于方法区的内存空间,除了类信息之外,还会存放有运行

随机推荐