jvm中的垃圾回收

一、垃圾回收的概念

   Java中的内存回收即Jvm运行时的内存的回收,需要回收的区域有方法区和Java堆。由于程序计数器,Java虚拟机栈和本地方法栈在方法结束或者是线程结束时会自动进行回收所以无须考虑回收。为什么需要垃圾回收呢?因为电脑中的内存的大小是有限而固定的,在运行过程中由于类的加载和创建,内存中已使用的内存会越来越大,导致后来的程序执行时无法进行分配内存进行执行,此时就需要进行垃圾回收,将已经使用的内存区域中没有在使用的数据清除,从而使后来的程序能够正常运行。

二、如何判断一个对象可以进行回收?

  在进行垃圾回收的时候,如何判断一个对象是否已经可以进行回收了呢?一个对象可以进行回收的时候就是不再有变量引用这个对象。常规去判断一个对象是否还有变量引用,使用的是引用计数法。就是给对象添加一个引用计数器,如果一个变量引用了这个对象,就把计数器里面的值加一,引用失效时就减一。进行垃圾回收的时候,对计数器里面的值为零的对象进行回收。但是主流的Java虚拟机并没有采用此种方法进行垃圾回收,而是采用GC Roots可达性算法进行判断一个对象是否可以进行回收。

  采用GC Roots可达性算法进行判断对象是否回收时,就是通过一系列可以作为GC Roots的对象作为起始点,向下搜索对象,形成多条对象可以GC Roots对象的路径,称为引用链,当一个对象不存在这个引用链中时,就可以进行回收。

  

  图中的对象A、B、C、D都存在路径(引用链)到达GC Roots对象,F则不存在,所以进行内存回收会回收对象F,而不会回收对象A,B,C,D。

三、垃圾回收算法

  Jvm中的内存回收使用以下几种回收算法:

  1.标记-清除算法:在进行垃圾回收的时候,将不再引用的对象进行标记,标记完成后,统一对于标记的对象进行回收。

  未回收时:

  

  进行标记-清除时,会对未引用对象进行全部标记,在标记完成后,对标记的未引用对象的内存进行回收。

  标记-清除后:

  

  2.标记-整理算法:在进行垃圾回收的时候,将不再引用的对象进行标记,标记完成后,统一对于标记的对象进行回收后,对内存进行整理,将引用对象移动到一起

  标记-整理之前:

  

  如同标记-清除方法一样,会对未引用对象进行标记,标记完成后进行清除,然后将还在引用对象的内存移动到一起

  标记整理后:

      

  3.复制算法::将内存划分成相等的两块内存,每次只使用其中一块内存进行分配,当正在使用内存中的空间使用完毕时,将使用的内存中的还存活的对象复制到另一块未使用的内存上,然后将清理已使用内存的空间。

  回收之前:

   

  复制算法回收之后:

  

  4.分代算法:将回收区分为新生代和老年代,新生代采用复制算法,老年代采用标记-清除或者是标记-整理算法

四、垃圾收集器  

  垃圾收集器就是垃圾回收算法的具体实现。Jvm中存在一下几种垃圾收集器

  

  1.Serial收集器:使用单线程对于垃圾进行回收,进行垃圾回收时必须停掉所有得工作进程进行垃圾回收,使用标记-整理算法。

  2..Serial Old收集器:Serial收集器的老年代版本。

  3.ParNew收集器:Seria收集器的多线程版本。

  4.Parallel Scavenge收集器:采用复制算法的收集器,控制吞吐量进行垃圾收集的算法,吞吐量即CPU运行用户代码的时间与CPU运行总时间的比值,用户可以通过设置吞吐量来控制垃圾回收的效率。

    5.Parallel Old收集器:Parallel Scavenge的老年代版本,采用标记整理算法和使用多线程回收。

  6.CMS收集器:以获得最短回收停顿时间为目标的收集器,采用标记-清除算法。回收的流程为:初始标记->并发标记->重新标记->并发清除.

  7.G1收集器:最新的收集器,回收流程为:初始标记->并发标记->最终标记->筛选回收。 

时间: 2024-08-09 02:18:15

jvm中的垃圾回收的相关文章

第四章 HotSpot jvm 中的垃圾回收机制

有很多有名的Jvm,但我们最常用到的就是Oracle收购sun公司的HotSpot. HotSpot中内存被分为3个代:年轻代(young generation),年老代(old generation),持久代(permanent generation).对象最初在年轻代,年老代代理存放着是经过几次年轻代收集后仍然 live 的对象和一些可能直接被分配到年老代的大对象.持久代存放的是 JVM 认为可以帮助简化垃圾收集管理的对象,比如像类和方法的描述信息. 年轻代代内存模型:一个伊甸区(Eden)

hotspot的JVM中的垃圾回收

有很多有名的Jvm,但我们最常用到的就是Oracle收购sun公司的HotSpot. HotSpot中内存被分为3个代:年轻代(young generation),年老代(old generation),持久代(permanent generation).对象最初在年轻代,年老代代理存放着是经过几次年轻代收集后仍然 live 的对象和一些可能直接被分配到年老代的大对象.持久代存放的是 JVM 认为可以帮助简化垃圾收集管理的对象,比如像类和方法的描述信息. 年轻代代内存模型:一个伊甸区(Eden)

Java性能优化之JVM GC(垃圾回收机制)

Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我们需要记住一个单词:stop-the-world .它会在任何一种GC算法中发生.stop-the-world 意味着JVM因为需要执行GC而停止了应用程序的执行.当stop-the-world 发生时,除GC所需的线程外,所有的线程都进入等待状态,直到GC任务完成.GC优化很多时候就是减少stop-the-world 的发生. JVM GC回收哪个区域内的垃圾? 需要注意的是,JV

深入理解JAVA虚拟机之JVM性能篇---垃圾回收

一.基本垃圾回收算法 1. 按基本回收策略分 1) 引用计数(Reference Counting)  对象增加一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的对象.此算法最致命的是无法处理循环引用的问题. 2)标记-清除(Mark-Sweep)  执行分两阶段.第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除. 缺点是此算法需要暂停整个应用,同时会产生内存碎片. 3)复制(Copying) 把内存空间划为两个相等的区域,每

JVM分代垃圾回收策略的基础概念

JVM分代垃圾回收策略的基础概念 由于不同对象的生命周期不一样,因此在JVM的垃圾回收策略中有分代这一策略.本文介绍了分代策略的目标,如何分代,以及垃圾回收的触发因素. 文章总结了JVM垃圾回收策略为什么要分代,如何分代,以及垃圾回收的触发因素. 为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的S

Java和.NET中的垃圾回收机制比较

相同点: 都采用了分代的机制. 都支持并发GC. 都没有采用引用计数方式,而是采用了追踪技术. .NET中,可以通过代码GC.Collect() 强制要求CLR进行垃圾回收(由于垃圾回收是异步的,CLR有一个专用的线程负责垃圾回收,因此,即使调用GC.Collect,也并不是实时的调用了Finalize,因此要保证确实调用了析构方法,可以使用语句GC.WaitForPendingFinalizers()来确保析构方法真的被运行了,参考http://cnn237111.blog.51cto.com

JVM基础(5)-垃圾回收机制

一.对象引用的类型 Java 中的垃圾回收一般是在 Java 堆中进行,因为堆中几乎存放了 Java 中所有的对象实例.谈到 Java 堆中的垃圾回收,自然要谈到引用.在 JDK1.2 之前,Java 中的引用定义很很纯粹:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用.但在 JDK1.2 之后,Java 对引用的概念进行了扩充,将其分为强引用(Strong Reference).软引用(Soft Reference).弱引用(Weak

[Java]理解JVM之四:垃圾回收机制

JVM内存中的各个区域都会回收吗? 首先我们知道 Java 栈和本地方法栈在方法执行完成后对应的栈帧就立刻出栈销毁,两者的回收率可以认为是100%:Java 堆中的对象在没有被引用后,即使用完成后会被回收:方法区中的数据一般不会回收,只有在同时满足:所有实例被回收.加载该类的类加载器被回收.Class对象无法通过任何途径访问(包括反射)时才会回收:而程序计数器主要是记录指令执行的信息,在 HostSpot 虚拟机中是不会被回收的: 对于堆中的垃圾回收机制如下: 一.何时触发对象的回收 对象没有被

【java虚拟机序列】java中的垃圾回收与内存分配策略

在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃圾回收(Garbage Collection,GC)是java语言的一大特色,在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理.而在C/C++中是需要程序员主动释放的,而在java中则交给JVM自动完成,既然是交给程序自动执行,那么这里就必须完成以下几件事: