小研究 - Java虚拟机垃圾收集器的性能分析与调节

垃圾收集器是Java虚拟机(JVM)的核心组成部分之一,对Java虚拟机的性能有非常重要的影响。本文将介绍GC的工作原理以及对象回收算法,重点介绍JVM的分段回收技术;剖析JVM自带的GC性能分析工具;阐述如何通过命令行参数调节GC的运行,提高 GC的效率。

目录

1  前 言

2  垃圾收集器(GC)

3  GC的性能分析

3.1  衡量 GC的主要性能指标

4  调整 GC的运行参数,提高GC性能

4.1  增大堆空间

4.2  调节Young分段和Old分段的比例

5  结束语


1  前 言

自Java平台,特别是Java2平台发布以来,已经有许多软件,特别是大型服务器软件采用Java平台进行开发和部署,比如Bea公司的 WebLogic、IBM公司的 WebSphere等。

Java的成功一方面是由于Java的跨平台性、开放性和完全面向对象特征,顺应了软件的发展方向,获得了软件厂商的广泛支持;另一方面,对于广大的开发人员来说,Java平台屏蔽了内存分配和回收的复杂性,把开发人员从繁重的内存管理中解脱出来,使开发人员专注于应用本身的逻辑处理,提高了程序开发的效率。

尽管Java平台的优点很多,应用也非常广泛,但是,不乏人们对Java应用的抱怨,这些抱怨主要来自两个方面,一是Java应用占用的内存太大,二是Java应用的性能低下。引起上述两个问题的原因可能是多方面,但是通常与JVM的垃圾收集器(GarbageCollector,GC)有密切的关系。本文接下去首先研究Sun公司的JVM(JavaHotspotVirtualMachine)的垃圾收集器,分析垃圾收集的原理和算法;然后阐述如何通过JVM的命令行参数调节GC的性能。

本文以J2SE1.4.1提供的JVM为基础介绍 GC,但是不介绍J2SE1.4.1新引入的两种 GC———并行收集器(Parellelcollector)和并发紧缩—标记收集器(Concurrentmark-sweepcollector),这两种收集器都是针对多个CPU和大尺寸堆(通常超过1G)的。

2  垃圾收集器(GC)

在Java中,程序员需要通过关键字new为每个对象申请内存空间,所有的对象都在堆(Heap)中分配空间,对象的回收是由GC决定和执行的。换句话说,内存的分配是由程序完成的,而内存的回收是有GC完成的。那么 GC如何判断一个对象是否需要回收呢?

在运行的应用程序中,一个对象如果没有其他任何对象指向,那么这个对象就是垃圾对象,GC就可以回收这个对象。

一个最直截了当的垃圾回收算法就是遍历所有可及的对象,所有剩下的就是垃圾对象。通常的垃圾收集算法有:标记—清除法、标记—紧缩法和拷贝法。

在前两种方法中,都需要首先标记出所有的垃圾对象,标记垃圾对象的方法一种是引用计数法(ReferenceCounting),引用计数为0的对象就是垃圾对象,这种方法对于循环引用无能为力;一种是从根对象出发(例如全局对象)遍历所有可及的对象,标记出可用的对象,剩下的就是垃圾对象。在标记出所有垃圾对象之后,标记—清除法将无用对象占用的堆空间放入空闲队伍;标记—紧缩法与标记—清除法相似,只不过需要对堆空间进行整理以消除内存碎片,堆整理非常慢。

拷贝法与前面两种方法不同,在这种方法中,整个堆被分成相等的两块。在任意时刻,只有其中的一块用于分配对象,另一块是空的。在垃圾回收时,用于分配对象的一块称为源块,空的一块称为目的块,所有从根对象出发可及的对象都从源块拷贝到目的块,在下一次垃圾回收时,源块和目的块互换。这种方法效率很高,而且不存在内存碎片,缺点是被分配的内存只有一半是可用的,一半是空闲的。

Sun公司提供的Java虚拟机采用的是另外一种方法,称为“分段”垃圾收集(GenerationalGarbageCollection)。这种方法是基于一个事实,绝大多数对象“存活”的时间很短。研究表明,在大多数程序中,绝大多数对象(超过95%)都是临时对象,存活的时间很短。

为了充分利用这个事实,提高 GC的效率,JVM 对堆的管理是“分段”进行的,每个分段分别保存着不同年龄阶段的对象,当有一个分段被分配完时,启动相应的垃圾收集器。

如图1所示,这是Sun的JVM堆分段划分示意图:

整个地址空间被分成两段,一个“Old”分段,用于保存已经存活时间较长的对象;一个“Young”分段,存活时间还不长的对象。Young分段由一个“Eden”空间和两个“Survivor”空间组成。Young分段采用拷贝法进行垃圾回收,通常称为“辅回收(minorcollection)”,它的作用范围仅仅是Young分段中的对象,速度快,效率高,发生的频率比较高;Old分段通过标记—紧缩法进行垃圾收集,通常称为“主回收(majorcollection)”,它的作用范围是整个堆空间中的所有对象,速度慢。在一个应用程序中,频繁发生的是辅回收。

整个地址空间被分成两段,一个“Old”分段,用于保存已经存活时间较长的对象;一个“Young”分段,存活时间还不长的对象。Young分段由一个“Eden”空间和两个“Survivor”空间组成。

Young分段采用拷贝法进行垃圾回收,通常称为“辅回收(minorcollection)”,它的作用范围仅仅是Young分段中的对象,速度快,效率高,发生的频率比较高;Old分段通过标记—紧缩法进行垃圾收集,通常称为“主回收(majorcollection)”,它的作用范围是整个堆空间中的所有对象,速度慢。在一个应用程序中,频繁发生的是辅回收。

3  GC的性能分析

3.1  衡量 GC的主要性能指标

衡量 GC的性能主要有两个指标———吞吐量(Throughout)和“暂停(Pause)”。吞吐量指应用程序运行一段较长的时间后,不用在GC上的时间占总时间的百分数,包括对象分配的时间。“暂停”是由于GC运行使得应用程序暂停运行。

不同的应用程序对这两个性能指标的要求可能不一样。比如,Web应用程序,比较注重吞吐量,对于 GC引起的“暂停”可能要求不高。但是如果对于Swing界面应用,则强调响应速度,就是说每次“暂停”时间不能太长。

3.2  性能分析的方法

JVM在运行过程中记录下许多有用的信息,包括 GC的详细信息,可以通过命令行参数使JVM 输出这些信息,这些信息是我们进行性能分析的依据。目前,许多性能分析工具都是以这些 信 息 为 基 础 的,例 如,免 费 的 PerfAnal、Sun 公 司 的 HeapAnalysisTool1.0.3(HAT)等。下面介绍通过命令行参数获得JVM的运行信息的方法。

-verbose:gc

输出每次垃圾回收前、后堆的大小以及持续的时间。如下是输出片断:

[GC12818K->12728K(13772K),0.0046039secs]
[FullGC12728K->6792K(13772K),0.1376320secs]

第一条记录表示辅回放,箭头前面表示垃圾回收之前已经分配的堆大小,箭头之后表示回收之后实际的堆大小,括号中表示JVM的总的堆大小,最后一项表示运行时间。第二条记录表示主回收。主回收持续的时间比辅回收要长的多。

-Xloggc:<filename>

获得每次垃圾回收的开始时间、回收前后堆的大小以及持续的时间,输出的信息写入filename指定的文件。如下是文件片断:

5.02112:[GC5812K->2187K(65088K),0.0161182secs]
5.84255:[GC6283K->2573K(65088K),0.0173578secs]

中括号之前的数字,表示每次垃圾回收开始的时间,括号中各数据的意义与上文介绍的相同。

-XX:+PrintGCDetails

输出 Young分段和Old分段垃圾回收前后各自的大小以及每次垃圾回收持续的时间。如下是输出片断:

[GC[DefNew:592K->64k(640K),0.0040581secs]7614k->7431K
(8848K),0.0043531]secs][FullGC[Tenured:7367K->6210K(8208K),0.1380240secs]7599K-
>6210K(8848K),0.1383776secs]

第一条 记 录 表 示 一 次 辅 回 收,DefNew 所 在 的 括 号 表 示Young分段的情况,总的Young分段为640K;第二条记录是主回收,Tenured所在的括号表示 Old分段的情况,总的 Old分段为8208K。

-XX:+PrintTenuringDistribution

输出在 Young分段上,各个年龄阶段的对象所占的字节数。如下是输出片断:

Desiredsurvivorsize32768bytes,newthreshold31(max31)-age 1:  6288bytes, 6288total
Desiredsurvivorsize32768bytes,newthreshold31(max31)-age 1:  3960bytes, 3960total-age 2:  5448bytes, 9408total

年龄为age1的对象表示首次进入Survivor空间的对象,年龄为age2的对象表示首次从Survivor空间拷贝到另一个Survi-vor空间的对象,age3的对象表示在Survivor空间之前拷贝2次,age4的对象在Survivor拷贝3次,依次类推。

hreshold表示年龄大于这个数目的对象进入 Old分段,最大值为31,也就说,对象在Survivor之间最多只能拷贝30次,之后若还存活,就必须进入 Old分段。

-Xrunhprof

这个 参 数 在 冒 号 之 后 还 可 以 带 有 参 数,可 以 通 过java-Xrunhprof:help命令查看,通过这个参数可以输出相当丰富的信息,包括每个方法占用的运行时间、每个对象什么时候被分配、占用空间的大小。

4  调整 GC的运行参数,提高GC性能

4.1  增大堆空间

一般来说,在JVM 中,垃圾回收发生的频率与堆的大小成反比,因此,增加堆空间,有助于提高垃圾收集器的性能。我们可以通过命令行参数-Xms和-Xmx设置应用程序的初始堆大小和最大堆大小。为了提高内存空间的利用率,JVM在每次垃圾回收之后都要检查堆的空闲率,空闲率的范围是通过参数:-XX:MinHeapFreeRatio=<mininum> 和-XX:MaxHeap-FreeRatio=<maximun>设置的,如果空闲率低于 mininum,JVM就会增大堆,但不会超过-Xmx设置的大小;如果空闲率超过max-imun,JVM就会减小堆,但不会小于-Xms设置的大小。

以如 下 机 器 配 置 为 例:Celeron1.7G,256 兆 DDR,Win-dows2000Professional,jdk1.4.1,Tomcat4.1.12。在某次运行:

ava-Xms64M-client-jar-Duser.dir=″C:\Tomcat41″″C:\Tomcat41\bin
\bootstrap.jar″start

完全启动Tomcat需要进行21次辅回收,0次主回收;如果运行:

java-Xms2M-client-jar-Duser.dir=″C:\Tomcat41″″C:\Tomcat41\bin
\bootstrap.jar″start

则完全启动Tomcat需要进行169次辅回收,5次主回收。在 Windows环境下,JVM的缺省值如表1所示:

4.2  调节Young分段和Old分段的比例

对于一定大小的堆来说,增大Young分段,有利于减小辅回收发生的频率;反之,会使辅回收发生的频率增大。至于两种情况下,主回收发生的频率是否会有明显的变化,取决于应用程序中“长寿命”的对象数量。

命令行参数-XX:NewRatio=n,可以设置 Old分段与 Young分段之间的比例,比例越大,Old分段越大。

以上文所述及的机器配置为例,某次运行:

java-client-Xms12M-Xmx12m-XX:NewRatio=40-jar-Duser.
dir=″C:\Tomcat41″″C:\Tomcat41\bin\bootstrap.jar″start

完全启动Tomcat需要170次辅回收,0次主回收,向该服务器请求jsp页面(带有session对象),辅回收频率非常高,主回收频率也升高。如果运行:

java-client-Xms12M-Xmx12m-XX:NewRatio=2-jar-Duser.dir=″
C:\Tomcat41″″C:\Tomcat41\bin\bootstrap.jar″start

完全启动Tomcat需要21次辅回收,6次主回收,向该服务器请求jsp页面(带有session对象),主回收频率比前一种情况高得多,辅回收不再发生,甚至发生内存溢出。

产生上述情况的原因是Tomcat本身的“长寿命”对象并不多,但是,jsp运行起来后,保存客户端信息的“长寿命”对象增多,例如用户的session对象等。因此,对于“长寿命”对象比较多的应用程序,NewRatio值宜较大,增大Old分段;对于“长寿命”对象比较少的应用程序,NewRaito的值宜较小,增大Young分段。

至于Young分段的Survivor空间占 Young分段的比例,可以通过参数-XX:SurvivorRatio来设置,例如,-XX:SurvivorRatio=6设置survivor:eden为1:6,换句话说每个survivor的空间是 Young分段的八分之一。一般来说,Survivor空间不宜过大,因为,其中一个Survivor空间始终是空的。

在 Windows环境下,JVM的缺省值如表2所示。

上述实验数据针对不同配置的机器、操作系统和运行环境,可能有所不同。在应用中,需要根据实际要求和约束条件,反复试验和分析,才能得出最佳的参数配置。JVM的缺省参数,是针对小应用程序的,对于大型应用程序往往是不能够适应的。

5  结束语

虽然,JVM屏蔽了对象分配和回收的复杂性,但是并不是说开发人员可以对GC一无所知,因为GC对于应用程序的性能有着至关重要的影响,有些时候甚至成为应用程序的性能瓶颈。事实上,JVM本身提供分析 GC性能的多种途径,同时提供充足的参数用以调节GC的性能,在我们的简单实验中,这些参数对GC的性能有非常重要的影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/108138.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

十几款拿来就能用的炫酷表白代码

「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」:小白零基础《Python入门到精通》 表白代码 1、坐我女朋友好吗,不同意就关机.vbs2、坐我女朋友好吗&…

<八> objectARX开发:动态拖动Jig创建自定义实体

1、介绍 接上一篇文章,在某些情况下,CAD中的实体对象初始参数并不是固定的,我们需要通过jig动态拖动方式来绘制自定义实体,下面就用一个简单的例子来介绍一下自定义实体动态绘制。   实体形状:包括实体夹点和文字夹点拖动实现。 2、效果 3、源码 static void RYMyGrou…

CAN总线学习——物理层、数据链路层、CANopen协议

1、CAN总线介绍 1.1、CAN总线描述 (1)CAN总线支持多节点通信,但是节点不分区主从,也就是不存在一个节点来负责维护总线的通信;这点可以和I2C总线对对比,I2C是一主多从模式; (2)是差分、异步、串行总线,采用…

华为OD机试 - 求满足条件的最长子串的长度 - 双指针(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷&#…

无人驾驶领域的软件测试该如何开展?

无人驾驶汽车使用自主决策和控制系统,这种系统通常由多个软件和硬件组件组成。软件测试是必要的,因为它可以确保无人驾驶汽车的软件系统达到高度可靠性和安全性,以及提高无人驾驶汽车的性能和可靠性。 因此无人驾驶汽车是一定要进行严格的软件…

关于类的隐形生成函数

https://www.youtube.com/watch?ve8Cw17p_BiU&listPL5jc9xFGsL8FWtnZBeTqZBbniyw0uHyaH&index6 https://www.youtube.com/watch?vKMSYmY74AEs&listPLE28375D4AC946CC3&index4 如果只有copy asignment operator, 那么default construct will be generated as…

PyCharm软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 PyCharm是一种集成开发环境(IDE),专门为Python开发者设计。它是由捷克软件公司JetBrains开发的,为Python开发人员提供了高效、易用和功能丰富的工具集。 以下是PyCharm软件的主要…

【C语言】操作符大全(保姆级介绍)

🚩纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:C语言 🔥该篇将详细介绍各种操作符的功能。 目录: 📘 前言① 算术操作符②移位操作符③位操作符④赋值操…

JS-this知识点、面试题

一、this指向什么 1.简介 2.规则一:默认绑定 3.规则二:隐式绑定 4.规则四:new绑定 5.规则三:显式绑定 call、apply、bind 6.内置函数的绑定 7.规则优先级 8.this规则之外--es6剪头函数 9.ES6剪头函数this 二、This面试题 面试题…

解决Spring Boot项目中pom.xml环境配置 打包后生效 但idea版本运行无效的问题

上文 Spring Boot中通过maven进行多环境配置 中我们通过pom.xml配置了环境选择 但这个只有在打包出来的jar中生效 我们直接通过 idea启动 这个东西确实是有点问题 其实 我们执行一下 compile 手工编译一下 然后重新启动 很明显 我们这里配置就已经生效了 这个就是 我们每次…

成功解决SQL 错误 [22000]: 第3 行附近出现错误: 试图修改自增列[ID](达梦数据库)

当我们使用工具来手动修改自增列的自增ID时,可能会报如下异常 SQL 错误 [22000]: 第3 行附近出现错误:试图修改自增列[ID] 解决办法: 可以使用SQL语句来修改 ALTER TABLE "fdw"."SYSTEM_DICT_TYPE" DROP IDENTITY; UPDATE "f…

【python】python智能停车场数据分析(代码+数据集)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

LeetCode-738-单调递增的数字

题目描述&#xff1a; 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c;且数字呈 单调递增 。 解题思路&#xff1a; 先将int变成char[]&#xff0c;获取…

【JavaEE】Spring事务-@Transactional参数介绍-事务的隔离级别以及传播机制

【JavaEE】Spring事务&#xff08;2&#xff09; 文章目录 【JavaEE】Spring事务&#xff08;2&#xff09;1. Transactional 参数介绍1.1 value 和 transactionManager1.2 timeout1.3 readOnly1.4 后面四个1.5 isolation 与 propagation 2. Spring 事务隔离级别 - isolation2.…

Git入门

本文主要介绍Git的入门知识。首先讲述版本控制工具的一些背景&#xff0c; 然后介绍如何在你自己的系统上安装.配置和运行Git。学完本文,你将明白Git是怎么来的、为什么需要Git,并掌握使用Git的基础知识。 一、版本控制 什么是“版本控制”&#xff0c;为什么需要它?版本控制是…

5G NR:PRACH时域资源

PRACH occasion时域位置由高层参数RACH-ConfigGeneric->prach-ConfigurationIndex指示&#xff0c;根据小区不同的频域和模式&#xff0c;38.211的第6.3.3节中给出了prach-ConfigurationIndex所对应的表格。 小区频段为FR1&#xff0c;FDD模式(paired频谱)/SUL&#xff0c;…

RHCE——八、DNS域名解析服务器

RHCE 一、概述1、产生原因2、作用3、连接方式4、因特网的域名结构4.1 拓扑4.2 分类4.3 域名服务器类型划分 二、DNS域名解析过程1、分类2、解析图&#xff1a;2.1 图&#xff1a;2.2 过程分析 三、搭建DNS域名解析服务器1、概述2、安装软件3、/bind服务中三个关键文件4、配置文…

什么是 API ?

一、API 的定义&#xff1a;数据共享模式定义 4 大种类 作为互联网从业人员&#xff0c;API 这个词我耳朵都听起茧子了&#xff0c;那么 API 究竟是什么呢&#xff1f; API 即应用程序接口&#xff08;API&#xff1a;Application Program Interface&#xff09;&#xff0c;…

基于YOLOV8模型的课堂场景下人脸目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOV8模型的课堂场景下人脸目标检测系统可用于日常生活中检测与定位课堂场景下人脸&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检…

c#设计模式-创建型模式 之 原型模式

概述 原型模式是一种创建型设计模式&#xff0c;它允许你复制已有对象&#xff0c;而无需使代码依赖它们所属的类。新的对象可以通过原型模式对已有对象进行复制来获得&#xff0c;而不是每次都重新创建。 原型模式包含如下角色&#xff1a; 抽象原型类&#xff1a;规定了具…