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

news2024/9/21 22:35:20

垃圾收集器是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.coloradmin.cn/o/931965.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

加油站ai视觉分析检测预警

加油站ai视觉分析预警系统通过yolov8图像识别和行为分析,加油站ai视觉分析预警算法识别出打电话抽烟、烟火行为、静电释放时间是否合规、灭火器摆放以及人员工服等不符合规定的行为,并发出预警信号以提醒相关人员。YOLOv8 的推理过程和 YOLOv5 几乎一样&…

什么是异步编程?什么是回调地狱(callback hell)以及如何避免它?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 异步编程⭐ 回调地狱(Callback Hell)⭐ 如何避免回调地狱1. 使用Promise2. 使用async/await3. 模块化和分离 ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订…

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

目录 一、软件简介 二、软件下载 一、软件简介 Office是微软公司开发的一套办公软件套装,包括多个应用程序,如Word、Excel、PowerPoint等,是全球使用最广泛的办公软件之一。以下是Office软件的详细介绍。 1、Office的历史和演变 Office最…

基于和声算法优化的BP神经网络(预测应用) - 附代码

基于和声算法优化的BP神经网络(预测应用) - 附代码 文章目录 基于和声算法优化的BP神经网络(预测应用) - 附代码1.数据介绍2.和声优化BP神经网络2.1 BP神经网络参数设置2.2 和声算法应用 4.测试结果:5.Matlab代码 摘要…

go学习-指针 标识符

指针,以及标识符 1.指针 (1).基本介绍 1)基本数据类型,变量存的值,也叫值类型 2)获取变量的地址用&,比如 var num int ,获取num的地址:&num 3)指针类型&…

Java-Lambda表达式

引入 Lambda表达式是在JAVA 8 中引入的,初衷是进一步简化匿名类的语法(匿名类还需要在类中实现函数),并使JAVA走向函数式编程。 语法 (parameters) -> expression 或 (parameters) -> { statements; } 可选类型声明。…

手把手教你安装jdk8

前提 我们口中说的Java8、JDK8、JDK1.8都是一个东西 下载 官方下载链接:(非翻墙可访问) https://www.oracle.com/java/technologies/javase/jdk18-archive-downloads.html 选择如图链接下载:(win11,其他系统版本选择…

【C++】C/C++内存管理-new、delete

文章目录 一、C/C内存分布二、C/C中动态内存管理方式2.1 C语言中动态内存管理方式2.2 C内存管理方式 三、operator new和operator delete函数3.1 operator new和operator delete函数3.2 operator new与operator delete的类专属重载(了解) 四、new和delet…

elementui table 在浏览器分辨率变化的时候界面异常

异常点: 界面显示不完整,表格卡顿,界面已经刷新完成,但是表格的宽度还在一点一点变化,甚至有无线延伸的情况 思路: 1. 使用doLayout 这里官方文档有说明, 所以我的想法是,监听浏览…

Vue2项目练手——通用后台管理项目第一节

Vue2项目练手——通用后台管理项目 知识补充yarn和npm区别npm的缺点:yarn的优点 npm查看镜像和设置镜像 项目介绍项目的技术栈 项目搭建文件目录 创建路由,引入element-uirouter/index.jsmain.jspages/Users.vuepages/Main.vuepages/Home.vuepages/Login…

vue脚手架的安装并创建项目

在之前的练习中我们都是采用引入jquery、vue文件的形式,很多es6的新特性都是无法使用的,因此现在我们采用脚手架进行安装相关的配置。 1、下载node.js,使用其中内置的npm来下载安装包。 直接在官网中下载长期支持版本即可。点击进入node.js官…

建模杂谈系列234 基于图的程序改造

说明 为了进一步提升程序设计与运维的可靠性,我觉得(目前看来)只有依赖图的结构。 提升主要包含如下方面: 1 程序结构的简洁性:节点和边2 程序执行的可视化:交通图(红、黄、绿)3 程序支持的逻辑复杂性。…

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

目录 一、软件简介 二、软件下载 一、软件简介 Multisim软件是一款电路仿真和设计软件,由美国国家仪器公司(National Instruments)开发。它提供了一个交互式的图形界面,使用户能够轻松地构建和仿真电路。以下是Multisim软件的详…

什么是devos勒索病毒,中招之后该怎么办?勒索病毒解密,数据恢复

Devos勒索病毒是一种比较常见的勒索病毒病毒,它利用加密技术来锁定用户的文件,并要求支付赎金才能解锁。这种病毒已经引起了全球范围内的关注,也给众多的企业主和个人造成了不可估量的损失。 Devos勒索病毒的起源尚不清楚,但它的攻…

无涯教程-分类算法 - 逻辑回归

逻辑回归是一种监督学习分类算法,用于预测目标变量的概率,目标或因变量的性质是二分法,这意味着将只有两种可能的类。 简而言之,因变量本质上是二进制的,其数据编码为1(代表成功/是)或0(代表失败/否)。 在数学上&…

Linux保存退出和不保存退出命令

Vim编辑器 vim 要编辑的文件输入i进入编辑模式保存退出: 按Esc键退出insert模式,然后输入冒号(:),输入wq!可以保存并退出. 不保存退出: 按Esc键退出insert模式,然后输入冒号(:),输入q!可以不保存并退出。…

Autosar存储入门系列03_Autosar中NVM状态机及存储调用逻辑

本文框架 0.前言1. NVM状态机介绍2. NVM读/写基本逻辑2.1 NVM读操作2.2 NVM写操作2.2.1 实时写2.2.2 下电写 2.3 NVM写入注意事项 0.前言 本系列是Autosar存储入门系列,希望能从学习者的角度把存储相关的知识点梳理一遍,这个过程中如果大家觉得有讲得不…

图文并茂:Python Tkinter从入门到高级实战全解析

目录 介绍什么是Tkinter?准备工作第一个Tkinter程序界面布局事件处理补充知识点 文本输入框复选框和单选框列表框弹出对话框 综合案例:待办事项列表总结 介绍 欢迎来到本篇文章,我们将带您深入了解如何在Python中使用Tkinter库来创建图形用…

弯道超车必做好题集锦二(C语言选择题)

前言: 编程想要学的好,刷题少不了,我们不仅要多刷题,还要刷好题!为此我开启了一个弯道超车必做好题锦集的系列,每篇大约10题左右。此为第二篇选择题篇,该系列会不定期更新,后续还会…

【网络云盘客户端】——项目简介

项目简介 网络云盘客户端时基于QT/C框架实现了一个网络云盘客户端软件,主要功能包括用户的注册,登录,显示用户的个人文件列表,以及文件的上传,下载,删除,共享文件。 登录界面 主窗口界面 文件…