深入理解JVM(二)--垃圾收集算法】的更多相关文章

一. 概述 说起垃圾收集(Garbage Collection, GC), 大部分人都把这项技术当做Java语言的伴随生产物. 事实上, GC的历史远远比Java久远, 1960年 诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言. 当Lisp还在胚胎时期时,人们就在思考GC需要完成的三件事情: 哪些内存需要回收? 什么时候回收? 如何回收? 现在内存的动态分配与内存回收技术已经相当成熟, 那为什么我们还要去了解GC和内存分配呢? 答案很简单: 当需要排查各种内存溢出, 内…
1. 垃圾收集算法       JVM的垃圾收集算法在不同的JVM实现中有所不同,且在平时工作中一般不会深入到收集算法,因此只对算法做较为简单的介绍.       1.1 标记-清除算法           这种算法是非常直观的,也是最为基础的收集算法(Mark-Sweep)算法,这种算法将回收分为两个阶段:首先标记所有需要回收的对象,然后在完成标记后统一回收掉被标记的对象.这种算法是如此的基础,以至于后面的算法都是基于该思路,并对其确定进行改进所得的.           这种算法的缺点主要有…
1.概述 垃圾收集(Garbage Collection,GC). 当需要排查各种内存溢出.内存泄露问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节. Java内存运行时,程序计数器.虚拟机栈.本地方法栈三个区域随线程生,随线程灭:栈中的栈帧随方法的进入和退出,有条不紊的执行着出栈和入栈操作.每个栈帧分配的内存基本在类结构确定下来时就已知(尽管在运行期会由JIT编译器进行一些优化).这几个区域不需过多考虑回收问题. 2.对象存活状态 堆中几乎…
前言 很多人将垃圾收集(Garbage Collection)视为Java的伴生产物,实际1960年诞生的Lisp是第一门真正使用内存动态分配与垃圾手机技术的语言.在目前看来,内存的动态分配与内存回收已经相当成熟,但了解GC与内存分配还是非常有必要的,当排查内存溢出.内存泄漏问题,当垃圾手机称为系统高并发的瓶颈时,就需要我们对其实施必要的监控与调节. 在前面的篇章中我们了解到Java的运行时区域中的程序计数器.虚拟机栈.本地方法栈的内存分配与回收具有确定性,但Java堆不同,这部分内存的分配与回…
  通过前面的介绍我们了解了对象创建和销毁的过程.那么JVM中垃圾收集器具体对对象回收采用的是什么算法呢?本文主要记录下JVM中垃圾收集的几种算法. JVM的垃圾回收的算法 标记-清除算法(Mark-Sweep)   标记清除算法是最基础的回收算法,该算法分为两个阶段,即标记阶段和清除阶段. |阶段|说明 | |--|:--| | 标记阶段|先根据可达性分析算法找出需要回收的对象进行标记 | | 清除阶段| 统一回收被标记的对象| 参考<深入理解java虚拟机>: 从可达性分析算法角度看标记-…
1. 一些概念 1.1 垃圾&垃圾收集 垃圾:在 JVM 语境下,"垃圾"指的是死亡的对象所占据的堆空间. 垃圾收集:所谓"垃圾收集",就是将已分配出去.但不再使用的内存回收回来,以便能再次分配. 1.2 对象是否死亡 如何判断一个对象是否死亡(即不可能再被任何途径使用)?通常有以下两种方法: 1.2.1 引用计数法 引用计数法(Reference Counting):为每个对象添加一个引用计数器,用来统计指向该对象的引用个数.当有地方引用它时,计数器加一:…
1.垃圾收集对象 垃圾收集主要是针对堆和方法区进行. 程序计数器.虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收. 哪些内存需要回收? 死亡的对象-->对象存活判定算法(引用计数.可达性分析.finalize()方法). 什么时候回收? 垃圾收集算法. 如何回收? 垃圾收集器. 1.1.堆中对象存活判定算法 1. 引用计数算法 给对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1.引用…
Java虚拟机的内存模型分为五个部分.各自是:程序计数器.Java虚拟机栈.本地方法栈.堆.方法区. 这五个区域既然是存储空间,那么为了避免Java虚拟机在执行期间内存存满的情况,就必须得有一个垃圾收集者的角色.不定期地回收一些无效内存,以保障Java虚拟机可以健康地持续执行. 这个垃圾收集者就是寻常我们所说的"垃圾收集器".那么垃圾收集器在何时清扫内存?清扫哪些数据?这就是接下来我们要解决的问题. 程序计数器.Java虚拟机栈.本地方法栈都是线程私有的,也就是每条线程都拥有这三块区域…
判断哪些对象需要被回收 引用计数算法: 给对象中添加一个引用计数器,每当有一个地方引用时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象就是不可能再被使用的. 但是JVM没有使用此方法,因为此方法无法解决2个对象相互循环引用的问题. 可达性分析算法: 这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象…
一.判断对象是否可进行回收 1.引用计数算法 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象就是不可能再被使用的.但是主流的Java虚拟机里面没有选用引用计数算法来管理内存,最主要的原因是它很难解决对象之间相互循环引用的问题.代码示例如下: public class JVMTest { private JVMTest jvmTest = null; public static void main(String[] arg…
3.1 关于垃圾收集和内存分配 垃圾收集和内存分配主要针对的区域是Java虚拟机中的堆和方法区: 3.2 如何判断对象是否“存活”(存活判定算法) 垃圾收集器在回收对象前判断其是否“存活”的两个算法: 1.引用计数算法:一个对象在被引用之后这个计数器就加1,不被引用之后则减1,如果是0,那么就被回收,这个一般不被主流Java虚拟机所使用,原因:对象的循环引用会导致计数器始终不为0,那么就无法回收. 2.可达性分析算法:通过GC roots对象作为起点,向下搜索和它进行有效链接的对象,如果对象最终…
在主流的商用程序语言中大多都是用根搜索算法(GC Roots Tracing)判断对象是否存活,比如java,c#等.当从GC Roots到某个对象不可达,则证明此对象是不可用的,将要被回收. 商业虚拟机都采用分代收集算法,根据对象的存活周期的不同将内存分为几块:新生代,老年代. 新生代,每次垃圾收集都会有大批量对象死去,只有少量存活,所以适合采用“复制算法”: 老年代,对象存活率比较高,没有额外的分配担保,所以一般采用“标记-清理”活着“标记-整理”算法: 1.标记-清除 缺点: 效率低下,标…
前言 垃圾收集器作为内存回收的具体表现,Java虚拟机规范并未对垃圾收集器的实现做规定,因而不同版本的虚拟机有很大区别,因而我们在这里主要讨论基于Sun HotSpot虚拟机1.6版本Update22,此虚拟机包含的收集器如下所示: 如图展示了7种作用于不同分代的收集器,若两个收集器之间存在连线,说明他们可以搭配使用.我们堆收集器进行比较就是为了针对具体的情况选择最合适的收集器. 一.Serial收集器 Serial是最基本,最早的收集器,曾是JDK1.3.1之前的虚拟机新生代唯一选择,这个收集…
如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现. Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商.不同版本的虚拟机所提供的垃圾收集器都可能会有很大差别,并且一般都会提供参数供用户根据自己的应用特点和要求组合出各个年代所使用的收集器. HotSpot虚拟机的垃圾回收器 图中展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用.虚拟机所处的区域,则表示它是属于新生代收集器还是老年代收集器. 概念理解 并发和并行这两个…
堆里面存放着Java世界差点儿全部的对象实例,垃圾收集器在对堆进行回收前.第一件事情就是要确定这些对象之中哪些还存活,哪些已经死去.推断对象的生命周期是否结束有下面几种方法 引用计数法 详细操作是给对象加入一个引用计数器.每当有一个地方引用时.计数器的值就加1,:当引用失效时.计数器就减1.不论什么时刻计数器为0的对象就 是不可能再被使用的.客观的说引用计数器算法实现简单,判定效率也非常高,在大部分情况下他都是一个不错的算法.可是引用计数器有缺陷 举个简单的样例,对象A和对象B都有字段insta…
垃圾收集是java语言的亮点,大大提高了开发人员的效率. 垃圾收集即GC,当内存不足的时候触发,不同的jvm版本算法和机制都有差别. 我是李福春,我在准备面试,今天的问题是: jvm的垃圾回收算法有哪些?有哪些垃圾收集器? 答:jvm的垃圾回收首先需要标注出可回收的对象,采用的是可达图算法(从对象出发,绘制出出对象的引用关系图, 当从活动对象出发,在图中不可达的对象即可标注为可回收对象) jvm的垃圾回收算法有3种,列举如下: 1, 标记清除算法.(即把标注的可回收对象直接清理,这样会带来内存碎…
2.1 C.C++内存管理是由开发人员管理,而Java则交给了JVM进行自动管理 2.2 JVM运行时数据区:方法区.堆(运行时线程共享),虚拟机栈.本地方法栈.程序计数器(运行时线程隔离,私有) 1.程序计数器(Program Counter Register):每一个线程都独有一个程序计数器,并且分配了一块线程私有的小块内存,程序运行时,这个计数器会记录字节码文件运行的行数,当线程切换时,则通过这个行数继续执行下面的操作 2.虚拟机栈(Java Virtual Machine Stacks)…
Java是一门面向对象的语言,在Java程序运行的过程中,无时无刻都会有对象被创建出来,在程序语言中,创建对象(例如克隆,反序列化)通常仅仅是一个new关键字,但是在虚拟机中是怎样的呢?本文主要了解一下一个对象(仅代指普通对象,不包含Class类和数组)在虚拟机中的创建过程. 当虚拟机遇到一条new指令时,首先将去检查这个指令的参数能否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载,解析和初始化过,如果没有,那必须先执行相应的类的加载过程. 在类加载检查通过后,接下…
前言 总所周知,jvm的垃圾收集算法一般包括标记.清除.整理三个阶段,最近在看了有关于垃圾收集的标记算法,记录一下自己的理解. 垃圾收集中标记算法有两种:一种是引用计数法,一种是根搜索算法. 引用记数法 引用计数法非常容易理解,jvm为每一个对象设立一个引用计数器,当该对象被引用时,计数器就加一,引用取消时则减一. 当jvm开始gc时,jvm判断该对象的引用计数器是否为0,若为0则标记为可清除对象. 引用计数器有个致命的缺点是无法解决循环依赖问题,这也导致这个算法被弃用. 如下图所示,当对象A中…
前言 从如何判定对象消亡的角度出发,垃圾收集算法可以划分为"引用计数式垃圾收集"(Reference Counting GC)和"追踪式垃圾收集"(Tracing GC)两大类,这两类也常被称作"直接垃圾收集"和"间接垃圾收集".由于束流Java虚拟机中使用 的都是"追踪式垃圾收集",所以后续介绍的垃圾收集算法都是属于追踪式的垃圾收集. 分代式收集理论 当前商业虚拟机的垃圾收集器,大多数都遵循了"…
垃圾收集器与内存分配策略 前言:本文基于<深入java虚拟机>再加上个人的理解以及其他相关资料,对内容进行整理浓缩总结.本文中的图来自网络,感谢图的作者.如果有不正确的地方,欢迎指出. 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 回顾 上文介绍了jvm的内存区域以及介绍了内存的溢出情况. jvm区域分为5个,线程独有:虚拟机栈,本地方法栈,程序计数器.线程共享:方法区,堆 两种溢出:栈溢出(StackOverflowError),OutOfMemo…
JVM垃圾收集算法的具体实现有很多种,本文只是介绍实现这些垃圾收集算法的三种思想和发展过程.所有的垃圾收集算法的具体实现都是遵循这三种算法思想而实现的. 1.标记-清除算法 标记-清除(Mark-Sweep)算法是最基础的垃圾收集算法.正如其名字描述的那样,该算法分为两个阶段:"标记"和"清除".首先标记出所有可以被回收的对象,然后经过一轮垃圾回收将所有被标记的对象的内存空间释放,即清除可被回收的对象.标记-清除算法的执行过程如下图所示: 该算法的优点是逻辑简单,最…
一.在JVM中什么是垃圾?如何判断一个对象是否可被回收?哪些对象可以作为GC Roots的根 垃圾就是在内存中已经不再被使用到的空间就是垃圾. 1.引用计数法: 内部使用一个计数器,当有对象被引用+1,没有就-1,但是没有办法解决循环引用的问题,JVM不采用此类回收法 2.枚举根节点可达性分析(GC Root) 它必须是一组活跃的引用 思路:通过一系列名为GC Roots的对象作为起始点,从这个被称为GC Root的对象开始向下进行搜索,如果一个对象达到GC Roots 没有任何的引用链相连时,…
本文整理自周志明老师的<深入理解Java虚拟机-JVM高级特性与最佳实践>第3版的第二章和第三章. 加上了一些网上拼拼凑凑的图片,个人认为很多博客复制来复制去,最后的东西都看不懂,所以从书里码了一下知识点,也用作自己记忆. 一.一个命令 上面的结果显示了 jvm 的模式: Client VM(-client),为在客户端环境中减少启动时间而优化: Server VM(-server),为在服务器环境中最大化程序执行速度而设计. 在文件路径:jdk-11.0.7+10\lib 下面可以更改 jv…
垃圾收集器 判断对象是否需存活 回收堆 判断对象是否存活: 方法一:引用计数法.对象被引用一次就+1,当为0时回收对象.缺点:无法解决循环引用问题. 方法二:可达性分析算法.记录当前对象是否有和GC Roots中对象的引用链.(其中,可以作为GCRoots对象的有:虚拟机栈中引用的对象.方法去中类静态属性引用的对象.方法区中常量引用的对象.本地方法栈中引用的对象.) 不可达对象并不是一定被垃圾收集的,当这个对象有必要执行finalize()并finalize里自己和某个对象建立关联,即可在第二次…
JVM垃圾收集 1. 判断对象是否存活 引用计数算法 对象添加一个引用计数器,每个地方引用它,计数器值加+1:当引用失效,计算器值减1:任何时刻计数器为0的对象不可能被使用.引用计数算法实现简单,高效. 缺点:引用计数算法,很难解决相互引用的问题. objA.instance = B; objB.instance = C; 可达性分析算法 主流商用算法,通过一些列的"GC roots" 作为对象的起点,从这些节点开始向下搜索,锁走过的路径成为引用链(reference Chain),当…
垃圾收集算法 标记-清除算法 最基础的收集算法是"标记-清除"(Mark-Sweep)算法,分两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. 不足:一个是效率问题,标记和清除两个过程的效率都不高:另一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能导致以后在程序运行过程需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一个的垃圾收集动作. 复制算法 为了解决效率问题,一种称为复制(Copying)的收集算法出现了,它将可用…
程序计数器.虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收.垃圾回收主要是针对 Java 堆和方法区进行. 判断一个对象是否可回收 1. 引用计数算法 给对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1.引用计数为 0 的对象可被回收. 两个对象出现循环引用的情况下,此时引用计数器永远不为 0,导致无法对它们进行回收. public class ReferenceCountingGC…
Java虚拟机的内存模型分为五部分:程序计数器.Java虚拟机栈.本地方法栈.堆.方法区. 程序计数器.Java虚拟机栈.本地方法栈都是线程私有的,也就是每个线程都拥有这三个区域,而且这三个区域会随着线程的创建而开始,随着线程的结束而销毁,那么垃圾收集器在何时清理这三个区域的问题就解决了. 堆和方法区是所有线程共享的区域,并且是在JVM开启的时候创建一直运行到JVM停止,因此它没办法根据线程的创建而创建,根据线程的结束而结束.堆中存放JVM在运行期间的所有对象,虽然每个对象的内存大小在加载该对象…
 系列介绍|本系列主要是记录学习jvm过程中觉得重要的内容,方便以后复习 在说垃圾收集算法之前,先要说一下垃圾收集,从大的讲,垃圾收集需要考虑三件事情: 1.哪些内存需要回收 2.什么时候回收 3.如何回收 JVM在执行java程序时,把他管理的内存分为多个数据区域: 1.程序计数器(记录程序执行到哪了,各线程之间独立存储, 互不影响) 2.虚拟机栈(这个栈就是我们常说的jvm的“堆”和“栈”中的栈,这里存放的是编译期间可知的各种数据类型(8种基本类型).对象引用(reference类型,就是一…