Java虚拟机之垃圾收集过程

1、Java技术和JVM

1、JVM体系结构
HotSpot JVM拥有支持强大功能和功能基础的体系结构,并支持实现高性能和大规模可伸缩性的能力。 例如,HotSpot JVM JIT编译器会生成动态优化。

JVM主要的组件包括 classloader、运行时数据区和执行引擎。

2、调优关键组件
下图紫色高亮部分显示了与性能相关的JVM的关键组件。

在调整性能时,JVM有三个重点关注的组件:
堆是对象数据存储的地方。该区域由启动时选择的垃圾收集器管理。 大多数调优选项都与该区域有关,比如调整堆大小以及根据实际情况选择的最合适的垃圾收集器。 JIT编译器对性能有很大影响,但很少需要使用新版本的JVM进行调优。
3、性能基础
通常,在调优Java应用程序时,重点在于两个主要目标:响应性或吞吐量。

响应性
响应性是指应用程序或系统响应所请求数据的速度。例如:

  1. UI响应事件(Events)的速度
  2. 网站返回页面的速度
  3. 数据库查询返回的速度

吞吐量
吞吐量专注于在特定时间段内最大限度地提高应用程序的工作量。例如:

  1. 在给定时间内完成的交易数量。
  2. 批处理程序在一个小时内完成的作业数量。
  3. 在一个小时内完成的数据库查询的数量。

2、垃圾收集描述

什么是自动垃圾收集呢?

自动垃圾收集是查看堆内存的过程,识别哪些对象正在使用,哪些没有,以及删除未使用的对象。 一个正在使用的对象或一个被引用的对象,意味着你的程序的某个部分仍然保持着一个指向该对象的引用。 未使用的对象或未被引用的对象不再被程序的任何部分引用。 所以未被引用对象所使用的内存可以被回收。
在C程语言中,分配和释放内存是一个手动过程。 在Java中,释放内存的过程由垃圾收集器自动处理。 基本过程描述如下。

第一步:标记(Marking)
第一步就是找出哪些内存片段在使用,哪些没有用了。

第二部:正常删除
正常删除会删除掉标记过程中标记的未被引用的对象。

删除未被引用的对象后,内存分配器会保存可以分配新对象的可用空间块的引用。

第三部:压缩
为了进一步提高性能,除了删除未引用的对象之外,还可以压缩剩余的引用对象。 通过将引用对象移动到一起,这可以使得新的内存分配变得更加容易和快速。

为什么要分代收集?

如前所述,标记和压缩JVM中的所有对象效率不高。 随着越来越多的对象被分配,垃圾收集的时间也越来越长。 然而,应用程序的经验分析表明,大多数对象都是短生命周期的。

从上图可以看到,随着时间的推移,越来越少的对象保持着分配( remain allocated)的状态,大多数对象都是短生命周期的。
为了增强JVM的性能,堆内存被分解成了几块,采用分代式管理:年轻带,老年代和永久代。

年轻代:刚刚被new 出来的对象被分配在此区域。内存管理使用minor garbage collection(小GC).
老年代:新生代中执行小粒度的GC幸存下来的”老”对象,内存管理使用major garbage collection(大GC).
永久代:包含应用的类/方法信息, 以及JRE库的类和方法信息.

小GC:执行非常频繁, 而且速度特别快.
大GC:一般会比小GC慢十倍以上.
Stop the World:中断程序运行, 直至GC完成,大小GC都会发出”Stop the World”事件。

3、GC分代收集过程

1、创建新的对象

扫描二维码关注公众号,回复: 1035756 查看本文章

每当我们使用new创建一个对象时, 这个对象会被分配到新生代的Eden区域。

2、当Eden区域满时

当Eden区域满时,就触发小GC。

引用可达的对象会移到Survivor(幸存者)区域–S0, 然后清空Eden区域, 此时引用不可达的对象会直接删除。

3、Eden再次满时
当Eden区域再次分配完后, 小GC执行, 引用可达的对象会移到Survivor(幸存者)区域, 而引用不可达的对象会跟随Eden的清空而删除回收.

这次引用可达的对象移动到的是S1的幸存者区, S0区域也会执行小GC, 将其中还引用可达的对象移动到S1区, 且年龄+1. 然后清空S0, 回收其中引用不可达的对象。

此时, 所有引用可达的对象都在S1区, 且S1区的对象存在不同的年龄。

当Eden又满时, S0和S1的角色互换。

4、当Survivor区的对象年龄达到”老年线”时
经过多次小GC后,Survivor区的对象年龄持续增长, 当其中某些对象年龄达到”老年线”, 例如8岁时, 它们会”晋升”到老年区。

随着小GC继续发生,对象将继续被提升到老一代空间。

以上就是年轻代的整分配回收过程。 最终,将对老年代进行一次大GC来清理和整理该空间。

4、常见的堆相关开关

VM参数 参数描述
-Xms 设置初始堆大小
-Xmx 设置堆最大值
-Xmn 设置年轻代空间大小
-XX:PermSize 设置永久代初始大小
-XX:MaxPermSize 设置永久代最大值
-XX:SurvivorRatio 设置Eden区和survivor区的大小比例,默认是 8。
-XX:NewRatio 设置老年代/年轻代比例,默认是2

参考:
Java Garbage Collection Basics

猜你喜欢

转载自blog.csdn.net/iluojie/article/details/80158007