linuxsir首页 LinuxSir.Org | Linux、BSD、Solaris、Unix | 开源传万世,因有我参与欢迎您!
网站首页 | 设为首页 | 加入收藏
您所在的位置:主页 > Linux基础建设 >

初步认识Java虚拟机中的垃圾收集器

时间:2018-06-04  来源:未知  作者:admin666

前言

Java虚拟机的垃圾收集器是虚拟机内存的清道夫,它的存在让Java开发人员能将更多精力投入到业务研发上。了解垃圾收集器,并利用好这个工具,能更好的保障服务稳定性。这篇文章通过分析Java虚拟机内存模型,介绍垃圾收集器常用算法和收集器类别,使得垃圾收集器的配置和使用变得不再遥不可及。

Java虚拟机内存模型

Java虚拟机内存可以划分为:虚拟机栈、本地方法栈、JAVA堆内存、方法区(包含运行时常量池)、程序计数器、直接内存。

虚拟机栈

虚拟机栈是线程私有的,生命周期跟线程相同。也就是说一个线程被创建后,虚拟机为其分配了一个独立的栈帧来存储线程的局部变量、操作数、动态链接、方法出口等信息,当线程结束后,该栈帧也会被回收清理。

本地方法栈

本地方法栈是虚拟机的native方法执行期间使用的一个栈帧。

Java堆内存

堆内存是被所有线程共享的一块区域,用来存放对象实例和数组,属于内存中最大的一块区域,也是垃圾收集的主要区域。从垃圾收集的角度看,堆内存经常分为新生代和老年代。

方法区

方法区也是被所有线程共享的一块区域,用来存储被虚拟机加载的类信息、常量、静态变量、JIT编译后代码等数据。也可以成为永久代。

程序计数器

程序计数器是线程私有的,作为当前线程所执行的字节码的行号指示器,每个线程有一个程序计数器,用于记录CPU切换线程时记录当前线程的执行位置,以便下次继续从当前位置往下执行。

直接内存

这块不属于JAVA虚拟机内存,但使用频繁,也可称之为“堆外内存”

Java虚拟机垃圾收集器

根据上述对JAVA虚拟机内存区域模型的介绍,我们知道JAVA程序中的对象实例都存储在JAVA堆内存中,因此垃圾收集主要也是针对堆内存进行。为了更好的管理JAVA对象实例,并结合对象实例的生存时间长短,JAVA虚拟机将堆内存分为新生代和老年代,分别存储刚创建不久的对象和存活较长时间的对象实例,并采用分代收集的策略分别回收新生代和老年代的内存。

内存分配与回收策略

  • 1、 分代收集思路。根据JAVA对象的生存周期特点,虚拟机将堆内存分为新生代和老年代,并分别采用新生代和老年代的垃圾回收策略。
  • 2、 新生代细分为Eden区和两个Survivor区(即From区和To区)。大多数新生对象创建频繁,且存活时间短,为了提高新生代区域垃圾收集效率,新创建的对象存放在Eden区,当Eden区快满的时候,虚拟机对其触发一次Minor GC,将新生代存活对象移动到From区,原来From区的对象根据存活年龄决定放到To区还是老年代,然后清空Eden区和From区,接着将To区对象全部移到From区。
  • 3、 大对象直接进入老年代,可以配置新生代对象的最大值,对象超过这个值就直接进入老年代。
  • 4、 发起Minor GC前,会先判断老年代最大可用连续空间是否大于新生代对象占用的空间,如果小于或不允许冒险,则触发一次Full GC。

垃圾收集算法(3种基本算法)

  • 1、 复制算法。针对于新生代的垃圾收集算法。当新生代Eden区快满的时候,将Eden区对象复制到From区,将From区对象根据存活年龄决定复制到To区还是到老年代,然后清除Eden区和From区,接着将To区对象复制到From区。
  • 2、 标记-清除算法。垃圾收集算法标记出需要回收的对象,标记完成后直接统一回收。垃圾收集器使用可达性分析来判断哪些对象是否存活,通过设置一系列GC Roots节点(包括栈、方法区中的静态属性和常量所引用的对象,以及本地方法栈中引用的对象),从这类节点往下搜索,当对象不在GC Root节点的引用链上时,说明对象不可达,可以被回收。
  • 3、 标记-整理算法。垃圾收集算法标记出需要回收的对象,标记完成后将存活对象往内存的一端移动,然后直接清理掉端边界以外的内存。

常用垃圾收集器

由于虚拟机中的垃圾收集是分代收集的,新生代和老年代的垃圾收集策略不太一样,所以一般是使用针对新生代和老年代的垃圾收集器组合。

  • 1、 Serial GC。新生代收集器,采用复制算法,用于Client客户端新生代垃圾收集,针对内存占用较少的应用进行垃圾收集。
  • 2、 Serial Old GC。老年代收集器,采用标记-整理算法,用于Client客户端老年代垃圾收集,针对内存占用较少的应用进行垃圾收集。
  • 3、 Parallel Scavenge GC。新生代收集器,采用复制算法,并行收集新生代内存垃圾,可以设置垃圾收集器的吞吐量,还可以设置自动适配调节吞吐量。
  • 4、 Parallel New GC。新生代收集器,采用复制算法,并行收集新生代内存垃圾。
  • 5、 Parallel Old GC。老年代收集器,采用标记-整理算法,并行收集老年代内存垃圾。
  • 6、 CMS GC。老年代收集器,采用标记-清除算法,并行收集老年代内存垃圾,不整理内存。由于在执行垃圾收集期间不中断业务线程,所以容易产出“浮动垃圾”,导致Full GC。可以通过设置参数来触发内存整理任务。
  • 7、 G1 GC。不再将堆内存区分新生代和老年代,而是将堆内存看作若干个均分小区域,并对最空闲的内存区域进行标记和回收。适用于大内存的应用。

配置垃圾收集机器参数

  • 1、UseSerialGC:虚拟机允许在Client模式下的默认值,打开此配置后,虚拟机使用Serial GC + Serial Old GC 的收集器组合进行内存回收。
  • 2、UseParNewGc:使用ParNew + Serial Old 的收集器组合进行内存回收。
  • 3、UseConcMarkSweepGC:使用ParNew + CMS + Serial Old GC的收集器组合进行内存回收。
  • 4、UseParallelGC:虚拟机允许在Server模式下的默认值,使用Parallel Scavenge + Serial Old 的收集器组合进行内存回收。
  • 5、UseParallelOldGC: 使用Parallel Scavenge + Parallel Old GC的收集器组合进行内存回收。
  • 6、SuriviorRatio:新生代中Eden区域与Surivior区域的容量比值,默认是8:1。
  • 7、PretenureSizeThreshold:设置这个值后,大于这个值的对象直接进入老年代。
  • 8、MaxtenuringThreshold:对象年龄超过这个值时进入老年代。
  • 9、ParallelGCThreads:设置并行GC时进行内存回收的线程数。
  • 10、UseAdaptiveSizePolicy:动态调整堆内存中各个区域的大小和进入老年代的对象年龄。
  • 11、HandlerPromotionFailure:是否允许分配担保失败。
  • 12、GCTimeRatio:仅在Parallel ScaVenge收集器时生效,设置GC时间占总运行时间的比率,默认为1%。
  • 13、MaxGCPauseMills:仅在Parallel ScaVenge收集器时生效,设置GC的最大停顿时间。
  • 14、CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发垃圾收集,默认68%,在设置CMS收集器时生效。
  • 15、UseCMSCompactAtFullCollection:在设置CMS收集器时生效,设置CMS收集器在完成垃圾收集后是否进行一次碎片整理。
  • 16、CMSFullGCsBeforeCompaction:仅在使用CMS时生效,设置CMS收集器在进行若干次收集后再启动一次内存碎片整理。
友情链接
  • Mozilla发布Firefox 67.0.4,修复沙箱逃逸漏洞
  • 蚂蚁金服正式成为CNCF云原生计算基金会黄金会员
  • Firefox 68将采用Microsoft BITS安装更新
  • OpenSSH增加对存储在RAM中的私钥的保护
  • 谷歌想实现自己的curl,为什么?
  • Raspberry Pi 4发布:更快的CPU、更大的内存
  • Firefox的UA将移除CPU架构信息
  • Ubuntu放弃支持32位应用程序实属乌龙,Steam会否重回Ubuntu怀抱
  • Qt 5.13稳定版发布:引入glTF 2.0、改进Wayland以及支持Lottie动
  • 红帽企业Linux 7现已内置Redis 5最新版
  • Slack进入微软内部禁用服务清单,GitHub也在其列?
  • 安全的全新编程语言V发布首个可用版本
  • Windows Terminal已上架,快尝鲜
  • 阿里巴巴微服务开源生态报告No.1
  • 面世两年,Google地球将支持所有基于Chromium的浏览器
  • 推进企业容器化持续创新,Rancher ECIC千人盛典完美收官
  • CentOS 8.0最新构建状态公布,或于数周后发布
  • Debian移植RISC
  • 微软拆分操作系统的计划初现雏形
  • Oracle发布基于VS Code的开发者工具,轻松使用Oracle数据库
  • Ubuntu 19.10停止支持32位的x86架构
  • 微软为Windows Terminal推出全新logo
  • 联想ThinkPad P系列笔记本预装Ubuntu系统
  • 微软发布适用于Win7/8的Microsoft Edge预览版
  • 启智平台发布联邦学习开源数据协作项目OpenI纵横
  • 经过六个多月的延迟,微软终于推出Hyper
  • ZFS On Linux 0.8.1 发布,Python可移植性工作
  • DragonFly BSD 5.6.0 发布,HAMMER2状态良好
  • Linux Kernel 5.2
  • CentOS 8.0 看起来还需要几周的时间
  • 百度网盘Linux版正式发布
  • PCIe 6.0宣布:带宽翻倍 狂飙至256GB/s
  • PHP 7.4 Alpha 发布,FFI扩展,预加载Opcache以获得更好的性能
  • Canonical将在未来的Ubuntu版本中放弃对32位架构的支持
  • Scala 2.13 发布,改进的编译器性能
  • 微软的GitHub收购了Pull Panda,并且使所有订阅完全免费
  • Windows Subsystem for Linux 2 (WSL 2)现在适用于Windows 10用
  • Debian 10 “Buster”的RISC
  • MariaDB宣布发布MariaDB Enterprise Server 10.4
  • DXVK 1.2.2 发布,带来微小的CPU开销优化
  • DragonFlyBSD 5.6 RC1 发布,VM优化,默认为HAMMER2
  • PrimeNG 8.0.0 发布,支持Angular 8,FocusTrap等
  • GIMP 2.10.12 发布,一些有用的改进
  • 清华大学Anaconda 镜像服务即将恢复
  • Debian GNU/Linux 10 “Buster” 操作系统将于2019年7月6日发布
  • 时时彩论坛
  • 五星体育斯诺克
  • 北单比分直播
  • 河北11选5走势图
  • 福建体彩36选7开奖结果
  • 九龙图库下载