`
ayufox
  • 浏览: 272779 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

[Java性能剖析]Sun JVM内存管理和垃圾回收

    博客分类:
  • JVM
阅读更多

       内存管理和垃圾回收是JVM非常关键的点,对Java性能的剖析而言,了解内存管理和垃圾回收的基本策略非常重要。本篇对Sun JVM 6.0的内存管理和垃圾回收做大概的描述。

      1.内存管理
      在程序运行过程当中,会创建大量的对象,这些对象,大部分是短周期的对象,小部分是长周期的对象,对于短周期的对象,需要频繁地进行垃圾回收以保证无用对象尽早被释放掉,对于长周期对象,则不需要频率垃圾回收以确保无谓地垃圾扫描检测。为解决这种矛盾,Sun JVM的内存管理采用分代的策略。
      1)年轻代(Young Gen):年轻代主要存放新创建的对象,内存大小相对会比较小,垃圾回收会比较频繁。年轻代分成1个Eden Space和2个Suvivor Space(命名为A和B)

  • 当对象在堆创建时,将进入年轻代的Eden Space。
  • 垃圾回收器进行垃圾回收时,扫描Eden Space和A Suvivor Space,如果对象仍然存活,则复制到B Suvivor Space,如果B Suvivor Space已经满,则复制 Old Gen
  • 扫描A Suvivor Space时,如果对象已经经过了几次的扫描仍然存活,JVM认为其为一个Old对象,则将其移到Old Gen。
  • 扫描完毕后,JVM将Eden Space和A Suvivor Space清空,然后交换A和B的角色(即下次垃圾回收时会扫描Eden Space和BSuvivor Space。

      我们可以看到:Young Gen垃圾回收时,采用将存活对象复制到到空的Suvivor Space的方式来确保不存在内存碎片,采用空间换时间的方式来加速内存垃圾回收。
      2)年老代(Tenured Gen):年老代主要存放JVM认为比较old的对象(经过几次的Young Gen的垃圾回收后仍然存在),内存大小相对会比较大,垃圾回收也相对没有那么频繁(譬如可能几个小时一次)。年老代主要采用压缩的方式来避免内存碎片(将存活对象移动到内存片的一边),当然,有些垃圾回收器(譬如CMS垃圾回收器)出于效率的原因,可能会不进行压缩。
      3)持久代(Perm Gen):持久代主要存放类定义、字节码和常量等很少会变更的信息,关于这块的垃圾回收策略可以参考我的另一篇BLOG《Tomcat Context reloadabled 与 OutOfMemory(PermSpace) 》。
      Class data sharing (CDS)( http://java.sun.com/j2se/1.5.0/docs/guide/vm/class-data-sharing.html)是JDK5新引入的特性,采用在虚拟机之间共享一些class定义信息(bootstrapClassLoader加载的类)的方式提速JVM的启动和内存的占用,主要用于客户端,如果需要对类进行instrutment,最好把CDS关闭。(默认情况下,JVM的server模式会关闭CDS,client模式会开启CDS)

-Xshare:off
Disable class data sharing.
-Xshare:on
Require class data sharing to be enabled. If it could not be enabled for various reasons, print an error message and exit.
-Xshare:auto
The default; enable class data sharing whenever possible.

 

       我们通过JConsole截图看看上面这几个区的显示(下图),从左到右分别是EdenSpace、A Suvivor Space、Tenured Gen、Code Cache、Perm Gen(shared-wr)、Perm Gen(shared-ro)、Perm Gen

      2.垃圾回收策略
      评估垃圾回收策略的两个重要度量是:

  • 吞吐量(Throughput ):JVM花费在垃圾回收上的时间越长,则吞吐量越低
  • 暂停时间(Pause time):JVM垃圾回收过程当中有一个暂停期,在暂停期间,应用程序不能运行,暂停时间是暂停期的长度

      非常遗憾的是,一般这两个指标是相互冲突的,改善其中一个会影响到另外一个,根据情景的不同我们决定是优先考虑吞吐量还是暂停时间,对于需要实时响应的应用,我们需要优先考虑暂停时间,对于后台运行应用,我们需要优先考虑吞吐量。
      在考察各种垃圾回收器之前,我们需要了解一下几个重要的策略

  • 并行(Parallel):并行表示使用多个线程同时进行垃圾回收的工作,此策略一般会从同时改善暂停时间和吞吐量,在有多CPU内核的服务器上,这是基本上我们要使用的策略。
  • 并发(Concurrent):并行表示垃圾回收器的一些工作(譬如垃圾标记)与应用程序同时进行,这将更进一步缩短暂停时间,需要注意的是,同时垃圾回收器的复杂性会大大增大,基本上是会降低吞吐量,
  • 内存碎片处理:有不压缩、压缩和拷贝三种策略,从空间上讲,拷贝将花费更多的内存(譬如如上内存管理的Young Gen,需要维持一个额外的Suvivor空间),从时间上来讲,不压缩会减低创建对象时的内存分配效率,在垃圾回收上,拷贝策略会比压缩策略更高效。

      Sun JVM有4垃圾回收器:

  • Serial Collector:序列垃圾回收器,垃圾回收器对Young Gen和Tenured Gen都是使用单线的垃圾回收方式,对Young Gen,会使用拷贝策略避免内存碎片,对Old Gen,会使用压缩策略避免内存碎片。基本上,在对内核的服务器上应该避免使用这种方式。在JVM启动参数中使用-XX:+UseSerialGC启用Serial Collector。
  • Parallel Collector:并发垃圾回收器,垃圾回收器对Young Gen和Tenured Gen都是使用多线程并行垃圾回收的方式,对Young Gen,会使用拷贝策略避免内存碎片,对Old Gen,会使用压缩策略避免内存碎片。在JVM启动参数中使用-XX:+UseParallelGC启用Parallel Collector。
  • Parallel Compacting Collector:并行压缩垃圾回收器,与Parallel Collector垃圾回收类似,但对Tenured Gen会使用一种更有效的垃圾回收策略,此垃圾回收器在暂停时间上会更短。在JVM启动参数中使用-XX:+UseParallelOldGC启用Parallel Compacting Collector。
  • Concurrent Mark-Sweep (CMS) Collector:并发标志清除垃圾回收器,对Young Gen会使用与Parallel Collector同样的垃圾回收策略,对Tenured Gen,垃圾回收的垃圾标志线程与应用线程同时进行,而垃圾清除则需要暂停应用线程,但暂停时间会大大缩减,需要注意的是,由于垃圾回收过程更加复杂,会降低总体的吞吐量。

 

6
3
分享到:
评论
10 楼 zoutuo 2013-06-30  
前辈可否告知其中的“吞吐量”指的是什么?谢谢!
9 楼 beritha 2013-06-06  
cobrano1 写道
Concurrent Mark-Sweep (CMS) Collector 最后一种策略没有写上如何配置参数

-XX:+UseConcMarkSweepGC
8 楼 cobrano1 2012-06-20  
Concurrent Mark-Sweep (CMS) Collector 最后一种策略没有写上如何配置参数
7 楼 ayufox 2010-05-29  
ahuaxuan 写道

但是有一个点:
ayufox 写道

如果B Suvivor Space已经满,则复制 Old Gen
这句话你写的很模糊
我的理解是:
1.存活对象放不进B, 那么会选择存活对象中, 拷贝次数较高的搬移到old
2.存活对象大于B空间, 存活对象将被马上搬移到old

确实写地不够清晰,不够严谨
6 楼 ahuaxuan 2010-05-29  
ayufox 写道
ahuaxuan 写道
ayufox 写道
垃圾回收器进行垃圾回收时,扫描Eden Space和A Suvivor Space,如果对象仍然存活,则复制到B Suvivor Space,如果B Suvivor Space已经满,则复制 Old Gen
这个不一定, 由于A和B有一个总是为空, 所以扫描的时候有时候是扫描eden和A,下一次扫描就是eden和B.
扫描eden和A的时候, 存活的对象会搬到B, 扫描eden和B的时候, 存活的对象会搬到A.
当某个对象被如此拷贝的次数达到一定的量的时候,该对象才会搬到old

呵呵,你对我的理解好象有问题,在这里,B(先假设是空的)并不一定能够满足存放所有存活的Eden Space和A Suvivor Space的对象,另外,你这里的描述同样可以见我下面的说明
ayufox 写道
扫描完毕后,JVM将Eden Space和A Suvivor Space清空,然后交换A和B的角色(即下次垃圾回收时会扫描Eden Space和BSuvivor Space。


恩,对的, 一样的意思

但是有一个点:
ayufox 写道

如果B Suvivor Space已经满,则复制 Old Gen
这句话你写的很模糊
我的理解是:
1.存活对象放不进B, 那么会选择存活对象中, 拷贝次数较高的搬移到old
2.存活对象大于B空间, 存活对象将被马上搬移到old

5 楼 ayufox 2010-05-29  
ahuaxuan 写道
找到了, 呵呵
-XX:MaxTenuringThreshold=<value>
This switch determines how much the objects may age in the young generation before getting promoted to the older generation. The default value is 31. For a big enough young generation and "survivor space", the long-lived objects may be copied up to 31 times between the survivor spaces before they are finally promoted to the old generation.

4 楼 ayufox 2010-05-29  
ahuaxuan 写道
ayufox 写道
垃圾回收器进行垃圾回收时,扫描Eden Space和A Suvivor Space,如果对象仍然存活,则复制到B Suvivor Space,如果B Suvivor Space已经满,则复制 Old Gen
这个不一定, 由于A和B有一个总是为空, 所以扫描的时候有时候是扫描eden和A,下一次扫描就是eden和B.
扫描eden和A的时候, 存活的对象会搬到B, 扫描eden和B的时候, 存活的对象会搬到A.
当某个对象被如此拷贝的次数达到一定的量的时候,该对象才会搬到old

呵呵,你对我的理解好象有问题,在这里,B(先假设是空的)并不一定能够满足存放所有存活的Eden Space和A Suvivor Space的对象,另外,你这里的描述同样可以见我下面的说明
ayufox 写道
扫描完毕后,JVM将Eden Space和A Suvivor Space清空,然后交换A和B的角色(即下次垃圾回收时会扫描Eden Space和BSuvivor Space。

3 楼 ahuaxuan 2010-05-29  
找到了, 呵呵
-XX:MaxTenuringThreshold=<value>
This switch determines how much the objects may age in the young generation before getting promoted to the older generation. The default value is 31. For a big enough young generation and "survivor space", the long-lived objects may be copied up to 31 times between the survivor spaces before they are finally promoted to the old generation.
2 楼 ahuaxuan 2010-05-29  
ayufox 写道
垃圾回收器进行垃圾回收时,扫描Eden Space和A Suvivor Space,如果对象仍然存活,则复制到B Suvivor Space,如果B Suvivor Space已经满,则复制 Old Gen
这个不一定, 由于A和B有一个总是为空, 所以扫描的时候有时候是扫描eden和A,下一次扫描就是eden和B.
扫描eden和A的时候, 存活的对象会搬到B, 扫描eden和B的时候, 存活的对象会搬到A.
当某个对象被如此拷贝的次数达到一定的量的时候,该对象才会搬到old
1 楼 ahuaxuan 2010-05-29  

ayufox 写道
扫描A Suvivor Space时,如果对象已经经过了几次的扫描仍然存活,JVM认为其为一个Old对象,则将其移到Old Gen。
这里的次数是可以调整的, 默认的好像是31次

相关推荐

    Java算法题,数据结构分析和实现.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    数据结构与算法分析 Java语言描述 习题解答.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    《数据结构与算法分析(Java语言描述版本)》中介绍的算法与数据结构.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    精品:java虚拟机分析与优化PPT

    我们将分析它是如何进行垃圾回收,内存管理,堆压缩,以及其他高级特性。我们还将研究如何配置JVM使得性能得以最优化。演讲者将列出对于IBM和SUN JVM在1.4.2以及1.5版本上对WebSphere有用的一组调优参数。如果您对...

    常规Java工具,算法,加密,数据库,面试题,源代码分析,解决方案.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    运用SSM写的停车场管理系统,加入了车牌识别和数据分析.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    学生成绩管理分析系统 毕业设计.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    JAVA 堆栈内存分析

    圾回收完成后JVM 重新分配内存。 -Xss128k :设置每个线程的栈大小。JDK5.0 以后每个线程栈大小为1M,之前每个线程栈 大小为256K。应当根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个 值能生成更...

    2022 毕业设计,基于 Hadoop 的游戏数据分析系统.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    2019年美国数学建模竞赛资料与分析.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    2019年遥感图像稀疏表征与智能分析竞赛-语义分割组.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    医疗信息就诊系统系统.zip

    主要功能按照数据流量、流向及...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    JavaCommunity-后端技术栈,应有尽有.zip

    【JavaCommunity-后端技术栈,...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    [毕业设计]基于Spark网易云音乐数据分析.zip

    功能:【1.图计算 2....自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    【JavaCommunity-后端技术栈,应有尽有】面试分享、源码分析.zip

    健壮性与高性能:Java通过垃圾回收机制确保内存的有效管理,同时也能通过JIT编译器优化来提升运行时性能。 标准库丰富:Java拥有庞大的类库,如Java SE(Java Standard Edition)包含基础API,用于开发通用应用...

Global site tag (gtag.js) - Google Analytics