广告
返回顶部
首页 > 资讯 > 精选 >java基础之JVM中GC算法怎么用
  • 689
分享到

java基础之JVM中GC算法怎么用

javajvmgc 2023-05-30 21:05:57 689人浏览 安东尼
摘要

这篇文章主要介绍了Java基础之JVM中GC算法怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。JVM内存组成结构:(1)堆所有通过new创建的对象都是在堆中分配内存,其

这篇文章主要介绍了Java基础JVMGC算法怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

JVM内存组成结构:

java基础之JVM中GC算法怎么用

(1)堆

所有通过new创建的对象都是在堆中分配内存,其大小可以通过-Xmx和-Xms来控制,堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区。Survivor被划分为from space 和 to space组成,结构图如下:

java基础之JVM中GC算法怎么用

(2)栈

每个线程 执行每个方法的时候都会在栈中申请一个栈帧,每个栈帧包含局部变量区和操作数栈。用于存放此次方法调用过程中的临时变量,参数和中间结果

(3)本地方法栈

用于支持native方法的执行。存储了每个native方法调用的状态

(4)方法区

存放了要加载的类信息,静态变量,final类型的常量,属性和方法信息。JVM用持久代(permanet generation)来存放方法区,可通过-XX:PermSize和 -XX:MaxPermSize来指定最小值和最大值。

(5)程序计数器

每个线程私有,当前线程执行的字节码的行数。

JAVA堆内存分配机制

 java内存分配和回收概括地说:就是分代分配,分代回收。对象将根据存货的时间被分为:young generation, old generation,permanent generation。

java基础之JVM中GC算法怎么用

yong generation:对象被创建时,内存的分配首先发生在年轻代(大对象可以直接创建在old generation),大部分的对象在创建后很快不再使用,因此很快变得不可达,被young generation 的GC机制清理掉(IBM的研究表示,98%的对象都是很快消亡的),这个GC机制被称为Minor GC或者 Young GC;Minor GC并不代表内存不足。

young generation分为 3个区域, eden区,两个 survivor区(from survivor, to survivor),内存分配过程如下所示:

java基础之JVM中GC算法怎么用

绝大多数对象刚创建被分配在 eden区,其中的大多数对象很快就会消亡,eden区域是连续的内存空间,在其上分配内存极快。

最初一次,当eden区满的时候,执行 minor GC,将消亡的对象清理掉,并将eden,survivor 1剩余的对象复制到到一个存活区 Survivor 0(此时Survivor 1是空白的,两个Survivor总有一个是空白的)

下次eden满了,在执行一次 minor GC,将消亡的对象清理掉,存活的对象复制到survivor1中,清空eden区。将survivor 0 中消亡的对象清理掉,将其中可以晋级的对象晋级到old区,将存活的对象也复制到survivor 1中,清空survivor 0

当被两个存活期 来回复制了几次之后,(用-XX:maxTenuringThreshold 控制,大于该值进入old generation,但是这只是个最大值,并不代表一定是这个值,因为:为了能更好地适应不同程序的内存状况,虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。)仍然存活的对象,将被复制到old generation。

old generation:对象如果在young generation 存活了足够长的时间而没有被清理掉,则会被复制到old generation,old generation 的空间一般比young generation大得多,发生的GC次数也比年轻代少,当年老代内存不足时,将执行 Major GC,也叫 Full GC;

可以使用-XX:+UseAdaptiveSizePolicy开关来控制是否采用动态控制策略,如果动态控制,则动态调整Java堆中各个区域的大小以及进入老年代的年龄。

如果对象比较大,young generation空间不足,则大对象会直接分配到old generation(大对象可能提前触发GC,应尽少使用大对象,更少用短命的大对象)。用-XX:PretenureSizeThreshold来控制直接升入老年代的对象大小,大于这个值的对象会直接分配在老年代上。

可能存在年老代对象引用新生代对象的情况,如果需要执行Young GC,则可能需要查询整个老年代以确定是否可以清理回收,这显然是低效的。解决的方法是,年老代中维护一个512 byte的块——”card table“,所有老年代对象引用新生代对象的记录都记录在这里。Young GC时,只要查这里即可,不用再去查全部老年代,因此性能大大提高。

JAVA 不同代GC 机制

young generation:发生的GC是minor GC,使用停止-复制算法进行清理,将新生代内存分为:较大的eden,和两个相等survivor,每次进行清理时,把eden 和一个survivor中存活的对象 复制到另一个survivor中,如果存活的对象超过了survivor内存,则需要通过空间分配担保机制将一部分对象复制到old generation,然后清理掉eden,和刚才的survivor。可以通过 -XX:SurvivorRation参数来调整eden和survivor区的内存容量比值。默认是8,eden:survivor:survivor = 8:1:1。

old generation:发生major GC。存储的对象比young generation多得多,且存在很多大对象,对old generation进行内存清理,如果使用 停止-复制算法,相当低效,一般使用 标记-整理算法,标记出仍然存活的对象(存在引用),将所有存活的对象向一端移动,以保证内存的连续。

在发生Minor GC时,虚拟机会检查每次晋升进入老年代的大小是否大于老年代的剩余空间大小,如果大于,则直接触发一次Full GC,否则,就查看是否设置了-XX:+HandlePromotionFailure(允许担保失败),如果允许,则只会进行MinorGC,此时可以容忍内存分配失败;如果不允许,则仍然进行Full GC(这代表着如果设置-XX:+Handle PromotionFailure,则触发MinorGC就会同时触发Full GC,哪怕老年代还有很多内存,所以,最好不要这样做)。

old generation GC之 标记-清除法:标记出所有需要回收的对象(可达性分析),标记完成后统一清理掉所有被标记的对象。

java基础之JVM中GC算法怎么用

该算法有两个问题:

(1)下频率问题:标记和清除过程效率都不高

(2)空间问题:标记清除后会产生大量的不连续的内存碎片,空间碎片太多会导致在运行过程需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集。

    old generation GC之 标记整理算法:标记过程和标记清除算法一样,但是后续步骤不再对可回收对象直接清理,而是让所有存活对象都向一端移动,然后清理掉边界以外的内存。

java基础之JVM中GC算法怎么用

 permanent generation:永久代的垃圾收集分为两类:废弃的常量和不再被使用的类。

废弃常量:比如说我们在常量池中用intern()添个字符串常量“a”,但是现在的系统没有任何一个String对象叫“a”,所以这个常量就是废弃了。

不再被使用的类:

①该类的所有的实例都已经被回收,Java堆中不存在该类的任何实例。

②加载类的ClassLoader已经被回收

③没有该类的java.lang.Class对象被引用,即不能通过反射访问该类信息。

满足了上述三个条件只是满足了类回收的基本条件,是否回收不用的类需要看设置的-Xnoclassgc参数进行控制,还可以使用-verbose:class及-XX:+TraceClassLoading、 -XX:+TraceClassUnLoading查看类的加载和卸载信息。

在大量使用反射、动态代理、CGLib等bytecode框架的场景,以及动态生成jsP和OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出。

算法分析:

空间分配担保:

在执行Minor GC前, VM会首先检查老年代是否有足够的空间存放新生代尚存活对象, 由于新生代使用复制收集算法, 为了提升内存利用率, 只使用了其中一个Survivor作为轮换备份, 因此当出现大量对象在Minor GC后仍然存活的情况时, 就需要老年代进行分配担保, 让Survivor无法容纳的对象直接进入老年代, 但前提是老年代需要有足够的空间容纳这些存活对象. 但存活对象的大小在实际完成GC前是无法明确知道的, 因此Minor GC前, VM会先首先检查老年代连续空间是否大于新生代对象总大小或历次晋升的平均大小, 如果条件成立, 则进行Minor GC, 否则进行Full GC(让老年代腾出更多空间).然而取历次晋升的对象的平均大小也是有一定风险的, 如果某次Minor GC存活后的对象突增,远远高于平均值的话,依然可能导致担保失败(Handle Promotion Failure, 老年代也无法存放这些对象了), 此时就只好在失败后重新发起一次Full GC(让老年代腾出更多空间).

 GC回收对象确立:

引用计数:如果有引用这个对象的,对象计数器+1,引用失效,计数器-1,绝大多数情况下,这个算法高效简单,但是不能解决对象之间的循环引用的关系,所以没有被主流语言采用。

可达性算法:通过一系列的称为 GC Roots 的对象作为起点, 然后向下搜索; 搜索所走过的路径称为引用链/Reference Chain, 当一个对象到 GC Roots 没有任何引用链相连时, 即该对象不可达, 也就说明此对象是不可用的, 如下图: Object5、6、7 虽然互有关联, 但它们到GC Roots是不可达的, 因此也会被判定为可回收的对象:

java基础之JVM中GC算法怎么用

 在Java, 可作为GC Roots的对象包括:

方法区: 类静态属性引用的对象; 方法区: 常量引用的对象; 虚拟机栈(本地变量表)中引用的对象. 本地方法栈JNI(Native方法)中引用的对象。

可达性算法如果对象到GC Roots不可达也不是说这个对象会立即被回收,是需要经过一个两次标记过程的,第一次:是在可达性分析后发现没有与GC Roots相连接的引用链。第二次是判断是否需要执行finalize(),这个方法也是对象唯一能够进行自我救赎的机会了,但是不推荐使用,因为这个方法运行代价高,不确定性大,不能保证不同对象的执行顺序。如果不需要执行该方法,直接就进行回收,如果需要执行该方法,那么该对象会被放在一个F-Queue里。虽然会被执行,但是不一定保证能够执行成功,因为有可能会在这个方法执行过程中出现死循环等意外情况,所以虚拟机并不一定会等待这个方法执行结束才进行回收。如果在第二次标记的时候,该对象没有成功的自我拯救,那么就真的被回收了。

常用JVM配置参数

-XX:CMSInitiatingPermOccupancyFraction:当永久区占用率达到这一百分比时,启动CMS回收
-XX:CMSInitiatinGoccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发
-XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收
-XX:CMSFullGCsBeforeCompaction:设定进行多少次CMS垃圾回收后,进行一次内存压缩
-XX:NewRatio:新生代和老年代的比
-XX:ParallelCMSThreads:设定CMS的线程数量
-XX:ParallelGCThreads:设置用于垃圾回收的线程数
-XX:SurvivorRatio:设置eden区大小和survivior区大小的比例
-XX:+UseParNewGC:在新生代使用并行收集器
-XX:+UseParallelGC :新生代使用并行回收收集器
-XX:+UseParallelOldGC:老年代使用并行回收收集器
-XX:+UseSerialGC:在新生代和老年代使用串行收集器
-XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS+串行收集器
-XX:+UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的整理
-XX:+UseCMSInitiatingOccupancyOnly:表示只在到达阀值的时候,才进行CMS回收

(+不能省)
-Xms:设置堆的最小空间大小。
-Xmx:设置堆的最大空间大小。
-XX:NewSize设置新生代最小空间大小。
-XX:MaxNewSize设置新生代最大空间大小。
-XX:PermSize设置永久代最小空间大小。
-XX:MaxPermSize设置永久代最大空间大小。
-Xss:设置每个线程的堆栈大小

感谢你能够认真阅读完这篇文章,希望小编分享的“java基础之JVM中GC算法怎么用”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网精选频道,更多相关知识等着你来学习!

--结束END--

本文标题: java基础之JVM中GC算法怎么用

本文链接: https://www.lsjlt.com/news/221304.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • java基础之JVM中GC算法怎么用
    这篇文章主要介绍了java基础之JVM中GC算法怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。JVM内存组成结构:(1)堆所有通过new创建的对象都是在堆中分配内存,其...
    99+
    2023-05-30
    java jvm gc
  • java垃圾回收原理之GC算法基础
    正文: 相关术语翻译说明: Mark,标记; Sweep,清除; Compact,整理; 也有人翻译为压缩,译者认为GC时不存在压缩这回事。 Copy,复制; copy 用作名词时一...
    99+
    2022-11-13
  • Python中的GC算法怎么用
    本文小编为大家详细介绍“Python中的GC算法怎么用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python中的GC算法怎么用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。概念分为三点:引用标记-清除/分代...
    99+
    2023-06-30
  • 怎么在java中实现一个gc算法
    这期内容当中小编将会给大家带来有关怎么在java中实现一个gc算法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. ...
    99+
    2023-06-14
  • Java基础之FastJson怎么使用
    FastJson是一个Java的JSON解析库,可以将Java对象转换为JSON格式的字符串,也可以将JSON格式的字符串转换为Ja...
    99+
    2023-08-16
    Java FastJson
  • JVM的基础中什么新生代不用标记清除算法
    JVM的基础中什么新生代不用标记清除算法,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。新生代又分为Eden区和Survivor区,Surv...
    99+
    2022-10-19
  • java中GC算法和垃圾收集器怎么使用
    在Java中,GC(垃圾回收)算法和垃圾收集器是自动管理内存的关键组件。以下是关于如何使用GC算法和垃圾收集器的一些基本指南:1. ...
    99+
    2023-08-24
    java
  • Java基础之反射怎么使用
    本篇内容介绍了“Java基础之反射怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!反射是框架设计的灵魂(使用的前提条件:必须先得到代表...
    99+
    2023-07-05
  • Java基础之基本数据类型怎么用
    这篇文章主要为大家展示了“Java基础之基本数据类型怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java基础之基本数据类型怎么用”这篇文章吧。一、整型主要扩展一下不同进制的整型二进制、八...
    99+
    2023-06-20
  • ES6基础语法之class类怎么用
    这篇文章主要介绍了ES6基础语法之class类怎么用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇ES6基础语法之class类怎么用文章都会有所收获,下面我们一起来看看吧。一、class基本语法JavaScri...
    99+
    2023-06-30
  • ES6基础语法之函数怎么使用
    这篇“ES6基础语法之函数怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“ES6基础语法之函数怎么使用”文章吧。一、函...
    99+
    2023-06-30
  • Java基础中常量怎么用
    这篇文章主要为大家展示了“Java基础中常量怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java基础中常量怎么用”这篇文章吧。public class FinalVa...
    99+
    2023-06-02
  • ES6基础语法之Map和Set对象怎么用
    本篇内容主要讲解“ES6基础语法之Map和Set对象怎么用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“ES6基础语法之Map和Set对象怎么用”吧!一、Map对象Map 对象保存键值对。任何值...
    99+
    2023-06-30
  • Java基础之教你怎么用代码一键生成POJO
    目录一、前言二、使用三、代码用法解释四、完整代码一、前言 在写SpringBoot项目,有时候设计到的表有几十上百张,如果要一个一个手动创建JavaBean以及对应的mapper类的...
    99+
    2022-11-12
  • 「Java基础入门」Java中switch怎么使用枚举
    在Java开发中,switch语句是一种常用的流控制语句,用于根据不同的条件执行不同的代码块。而当使用枚举类型作为条件时,我们常常会遇到“Constant expression required”的报错问题,这给程序开发造成了不小的困扰。 ...
    99+
    2023-09-02
    java servlet jvm
  • 零基础怎么办?Java 存储 LeetCode 编程算法的最佳实践教程!
    Java 作为一门广泛应用的编程语言,它在算法编程领域也有着广泛的应用。如果你是一个零基础的 Java 编程学习者,那么你可能会感到困惑:如何存储 LeetCode 编程算法?这篇文章将会为你提供一些最佳实践教程,帮助你更好地存储和管理你的...
    99+
    2023-09-01
    存储 leetcode 编程算法
  • Java基础知识中ByteArrayOutputStream流的使用方法是什么
    Java基础知识中ByteArrayOutputStream流的使用方法是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Java ByteArrayOutputStream...
    99+
    2023-06-22
  • Java基础知识中StringWriter流的使用方法是什么
    本篇文章为大家展示了Java基础知识中StringWriter流的使用方法是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Java StringWriter流的使用一、StringWriter流...
    99+
    2023-06-22
  • Java排序算法之怎么实现快速排序的三数取中法
    这篇文章主要讲解了“Java排序算法之怎么实现快速排序的三数取中法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java排序算法之怎么实现快速排序的三数取中法”吧!基本步骤三数取中在快排的过...
    99+
    2023-06-25
  • Java编程中的分治算法怎么用
    Java编程中的分治算法怎么用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作