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

这篇具有很好参考价值的文章主要介绍了小研究 - 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堆分段划分示意图:

小研究 - Java虚拟机垃圾收集器的性能分析与调节,# 小研报,java,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所示:

小研究 - Java虚拟机垃圾收集器的性能分析与调节,# 小研报,java,jvm,开发语言,性能分析,性能调节

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所示。

小研究 - Java虚拟机垃圾收集器的性能分析与调节,# 小研报,java,jvm,开发语言,性能分析,性能调节

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

5  结束语

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

到了这里,关于小研究 - Java虚拟机垃圾收集器的性能分析与调节的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JVM 垃圾收集器

    重点:CMS,G1,ZGC 主要垃圾收集器如下,图中标出了它们的工作区域、垃圾收集算法,以及配合关系。 Serial 收集器 Serial 收集器是最基础、历史最悠久的收集器。 如同它的名字(串行),它是一个单线程工作的收集器,使用一个处理器或一条收集线程去完成垃圾收集工作。

    2024年02月10日
    浏览(50)
  • 垃圾收集器

    目录 1.垃圾判断 1.1 引用计数法: 1.2 可达性分析: 1.3 常见的GC Roots有: 2.垃圾回收方式:垃圾收集器 2.1 CMS收集器: 2.2 G1收集器: 1.1 引用计数法:         对象有一个引用计数器,引用一次计数器就加1,计数器为0就是没有引用,但存在循环引用问题 1.2 可达性分析:

    2024年02月11日
    浏览(41)
  • JVM垃圾回收——G1垃圾收集器

    目录 一、什么是G1垃圾收集器 二、G1垃圾收集器的内存划分 三、G1垃圾收集器的收集过程  四、G1收集器的优缺点 五、G1收集器的JVM参数配置         Garbage First(简称G1)收集器是垃圾收集器技术发展史上里程碑式的成果,它摒弃了传统垃圾收集器的严格的内存划分,而是采

    2024年02月05日
    浏览(46)
  • 【JVM】JVM垃圾收集器

    垃圾收集器是负责 执行垃圾回收的组件 ,它们用于 管理Java程序运行时的内存分配和释放 。垃圾收集器的主要任务是 自动回收不再使用的内存对象 ,并将 内存空间重新回收 以供程序继续使用。 Serial和Serial Old串行垃圾收集器,是指 使用单线程进行垃圾回收 ,堆内存较小,

    2024年02月13日
    浏览(43)
  • JVM:垃圾收集器(7种)

    如果两个收集器之间存在连线,就说明它们可以搭配使用。它们说在的区域则表示这个收集器属于新生代收集器还是老年代收集器。其中Serial(串行)、Parallel(并行)         Serial收集器是最基础、历史最悠久的收集器,是HotSpot虚拟机新生代收集器的唯一选择。这个收集器

    2024年01月20日
    浏览(50)
  • JVM--- 垃圾收集器详细整理

    目录 一、垃圾收集需要考虑的三个事情: 二、垃圾回收针对的区域 三、如何判断对象已死         1.引用计数算法:         2.可达性分析算法 四、引用 五、生存还是死亡? 六、回收方法区 七、垃圾收集算法         1.分代收集理论 2.标记-清除算法         3.标记

    2024年02月19日
    浏览(73)
  • JVM ZGC垃圾收集器

    ZGC(“Z”并非什么专业名词的缩写,这款收集器的名字就叫作Z Garbage Collector)是一款在JDK 11中新加入的具有实验性质[1]的低延迟垃圾收集器,是由Oracle公司研发的。 ZGC收集器 是一款基于Region内存布局的,(暂时)不设分代的,使用了读屏障、染色指针和内存多重映射等技术

    2024年02月10日
    浏览(49)
  • JVM的故事——垃圾收集器

    新生代收集器,最基础的收集器,单线程。进行垃圾收集时必须暂停其他所有工作线程,stop the world 新生代收集器,实质上是serial收集器的多线程版本。除了serial,只有它能和CMS收集器(老年代收集器)配合工作。随着处理器核心数越来越多,parnew比serial有着更好的性能。(但如

    2024年02月10日
    浏览(51)
  • 深入理解JVM垃圾收集器

    相关系列 深入理解JVM垃圾收集算法-CSDN博客 目前市面常见的垃圾收集器有Serial、ParNew、Parallel、CMS、Serial Old、Parallel Old、G1、ZGC以及有二种不常见的Epsilon、Shenandoah的,从上图可以看到有连线的的垃圾收集器是可以组合使用,是年轻代+老年代。为什么会出现这么多的垃圾收集

    2024年04月09日
    浏览(50)
  • 08-JVM垃圾收集器详解

    上一篇:07-垃圾收集算法详解 如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。 虽然我们对各个收集器进行比较,但并非为了挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现,更加没有万能的垃圾收集器,我们能做

    2024年02月09日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包