JVM中的垃圾回收器及垃圾收集算法描述

首先需要了解下JVM(Java虚拟机)中的内存分配情况:

收集器的介绍

Serial收集器:是最原始的收集器,是单线程的,实现简单,但是在后台收集垃圾的时候,其他的工作线程都会停止,直到垃圾收集线程执行完毕,给用户的体验就是出现停顿现象,体验差。但是当收集的垃圾少,停顿时间短,次数少,还是可以接受的。运行在Client模式下是一个很好的选择。
ParNew收集器:是Serial收集器的多线程办,不过在单处理器下效果不比Serial收集器效果好,多线程会采取对应的机制,默认开始的线程数量和CPU的数量相同。
CMS收集器:目标是缩短用户的停顿时间,即垃圾收集的时间,是并发收集器,是牺牲吞吐量和新生代空间来换取的。
Parallel Scavenge收集器:目标是达到一个可控的吞吐量(运行用户代码/(运行用户代码+垃圾收集时间)),被称为吞吐量优先的收集器。采用复制算法实现

算法

引用计数法:在对象中添加一个基数器,当有变量引用这个对象时,计数器就加一,当变量放开对这个对象的引用时,计数器就减一,当计数器的值为0时,表示没有引用这个对象的变量了,后续就可以被垃圾收集器处理了。
优缺点:实现简单,但针对互相引用的对象没办法进行清理。如:      objA.instance=objB;objB.instance=objA;这种情况下,其他变量引用这2个对象了,但是这两个   对象仍然不能删除,因为它们互相引用,计数器的值不为0.

可达性分析:以GC Roots为起点,从这些节点开始,向下搜索形成引用链,当GC Roots到某个对象为不可达时,表示这个对象就是一个无用的对象,可以在垃圾收集时进行处理。
标记-清处算法:进行2个过程,标记:把需要清理的对象都标记出来;清除:就是把标记的对象都清楚掉。这2个过程效率都不是很高,且会产生很多空间碎片,导致因为大对象没有连续的内存分配空间而引起再次的垃圾回收。

复制算法:标记-清除算法中存在效率和空间碎片问题,此复制算法可以解决效率问题,把内存空间分为等同大小的块,使用其中的一块进程分配,当内存用完时,把还存活的对象放到另一个内存中,然后把原理内存块一起清理掉,新块中根据指针按需分配排列。实现简单,效率好,但是会浪费一般的内存。
标记整理算法:此算法也是分为2步,第一步标记,第二步整理,标记和前面讲的标记一样,仅是第二步整理,是把存活的对象往一个方向移动,然后清除掉边缘部分。此种算法没有空间碎片的存在了。
分代收集算法:没有采用新的算法,而是根据对象的存活时间不同,把内存分为新生代和老年代,且由于新生代多为新创建的对象,需要的内存空间大,比例按照8:1:1进行划分内存的。然后根据区域的不同采用不同的收集算法,新生代的对象存活率低,可以使用复制算法,老年代的对象存活率高,可以采用标记清除或者标记整理算法。

GC日志

GC的日志格式就是时间+类型+内存数据等信息的构成
在日志结果中,可以观察到,使用的收集器是Parallel Scavenge收集器-> PSYoungGen,ps是缩写,默认的Default New Generation的是新生代是使用Serial收集器。名字与收集器有关。使用时根据具体的情况进行实例对象的分配,比如新生代中的Eden区内存不够时,接下来大的实例化对象存到survivor中也不够,则就会直接存储到老年区。

而使用Serial收集器时,先分配6M的新生代区域,后面的4M不够分配,会发生minor GC,在GC期间,6M的空间不足以分配到survivor区域(这个区域仅1M),所以会通过担保机制把6M的对象直接放入到老年区。使用的收集器不同得出的垃圾回收日志会不相同。
Minor GC:是指新生代的垃圾回收,一般java对象的生命周期都很短,minor GC频繁,回收也快。
Full GC:指老年代的回收,经常会伴随一次minor GC,但不是绝对的,Parallel Scavenge就可以直接Major GC,速度一般比minor GC 慢10倍以上。

测试代码如下所示:

package com.class01;

/**
 * @Author: guopengxia
 * @Date: 2019/3/22 19:09
 * @Version: 1.0
 */
public class Class01 {
    private static final int _1MB=1024*1024;
    /**
     * 设置VM的参数:
     *   -Xms20M  -Xmx20M  -Xmn10M    //Xms,Xmx设置堆内存的大小(20M) Xmn:设置年轻代大小
     *   -XX:PrintGCDetails   //设置打印GC的详细信息(收集器日志参数)
     *   -XX:SurvivorRatio=8  //设置老年区的比例信息,新生区Eden:其中一个Survivor的比例为8:1
     */

    public static void testAllocation(){
        byte [] allocation1,allocation2,allocation3,allocation4;
        allocation1=new byte[2*_1MB];
        allocation2=new byte[2*_1MB];
        allocation3=new byte[2*_1MB];
        allocation4=new byte[4*_1MB];  //此处会出现一次Minor GC(当新生代没有内存进行分配时,会出现Minor GC)
    }

    public static void main(String []args){
        Class01.testAllocation();
    }
}

下面是日志截图,这次是日志显示到控制台(可以把GC的信息打印到日志文件中,进行参数设置即可)

原文地址:https://www.cnblogs.com/guopengxia0719/p/10582140.html

时间: 2024-07-31 10:26:58

JVM中的垃圾回收器及垃圾收集算法描述的相关文章

JVM学习--(五)垃圾回收器

上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中,用户可以根据自身的需求,使用不同的垃圾回收器,以便让自己的java程序性能到达最佳. 在介绍垃圾回收器之前,我们先回顾一下java堆的结构. 堆内存回顾 java堆内存结构包括:新生代和老年代,其中新生代由一个伊甸区和2个幸存区组成,2个幸存区是大小相同,完全对称的,没有任何差别.我们把它们称为S0区和S1区,也可以称为from区和t

jvm中的垃圾回收

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

说一下 jvm 有哪些垃圾回收器?

新生代收集器: SerialParNewParallel Scavenge 老年代收集器: Serial OldCMSParallel Old 堆内存垃圾收集器: G1 参考链接:JVM常见的垃圾回收器 原文地址:https://www.cnblogs.com/jxxblogs/p/12208121.html

JVM垃圾回收2(垃圾收集算法)

根据<深入理解java虚拟机>这本书总结 一.关于几个概念:(标记垃圾算法.垃圾收集算法.垃圾收集器) 前面说了如何寻找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虚拟机解析篇之---垃圾回收器

上一篇说了虚拟机的内存模型,在说到堆内存的时候我们提到了,堆内存是Java内存中区域最大的一部分,而且垃圾回收器主要就是回收这部分的内容.那么这篇就来介绍一下垃圾回收器的原理以及回收的算法. Java中的垃圾回收器(GC)是Java中比较有特色的一点,不需要我们手动的去管理一个对象,不想C++中的构造函数和析构函数一样,需要程序猿自己去手动的管理,很容易造成内存泄露的问题.当然如果学过OC语言的话,我们知道OC语言中有自动释放池的概念,当然我们使用retain/release进行手动管理对象的.

[Think In Java]基础拾遗1 - 对象初始化、垃圾回收器、继承、组合、代理、接口、抽象类

目录 第一章 对象导论第二章 一切都是对象第三章 操作符第四章 控制执行流程第五章 初始化与清理第六章 访问权限控制第七章 复用类第九章 接口 第一章 对象导论 1. 对象的数据位于何处? 有两种方式在内存中存放对象: (1)为了追求最大的执行速度,对象的存储空间和生命周期可以在编写程序时确定,这可以通过将对象置于堆栈或者静态存储区域内来实现.这种方式牺牲了灵活性. (2)在被称为堆的内存池中动态地创建对象.在这种方式,知道运行时才知道对象需要多少对象,它们的生命周期如何,以及它们的具体类型.

JVM 垃圾回收器工作原理及使用实例介绍(转载自IBM),直接复制粘贴,需要原文戳链接

原文 https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/ 再插一个关于线程和进程上下文,待判断 http://blog.sina.com.cn/s/blog_75e9551f01016cm3.html 垃圾收集基础 Java 语言的一大特点就是可以进行自动垃圾回收处理,而无需开发人员过于关注系统资源,例如内存资源的释放情况.自动垃圾收集虽然大大减轻了开发人员的工作量,但是也增加了软件系统的负担. 拥有垃圾收集