`
phoenix520
  • 浏览: 140293 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java的垃圾回收器

    博客分类:
  • Java
 
阅读更多

原文在 http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html ,下面是个人的一些理解,可能有不对的地方。

  • 如果不指定-client或-server参数,JVM会根据系统状况自动判断使用client还是server模式,具体见这里。有趣的是,AMD64的CPU默认就是server模式(经测试,windows下仍然默认client模式),其他CPU时,除windows默认为client模式外,其他>=2C2G的电脑都会默认为server模式。
  • 如果不指定使用哪种垃圾回收器,JVM会根据应用程序运行的硬件情况(CPU/内存)来自动决定使用哪种GC、堆栈大小以及运行时编译器,也就是说,如果运行应用程序时不指定GC的参数,那么不同的硬件上使用的垃圾回收器可能是不同的。
  • 可以通过指定应用允许的最大暂停时间(full GC时程序会失去响应)和吞吐量来调节GC,而不是仅仅通过指定堆栈大小等参数来调节。
  • JVM中内存区域分为新生代、年老代和持久代,其中新生代又分为eden和两个 survivor 区,如下图(适用于 serial collector ):
大多数对象创建时,先存放在eden区,当eden区满了的时候,执行一次部分GC,将存活的对象拷贝到survivor 
两个survivor 区中,其中有一个始终为空的状态,执行部分GC时,另一个survivor 以及eden区中的live对象会被全部拷贝到这个区,这样来回移动移动数次,仍然存活的对象将拷贝到年老代。至于一个对象需要拷贝多少次才能移动到年老代,是在每次GC时由JVM决定的,JVM决定这个值的大小,以确保survivor区处于半满状态(其实根据实际监控来看,应该是保持在大半满靠全满状态),通过XX:+PrintTenuringDistribution可以查看该数值。在Jconsole中,查看survivor 区的时候,只能看到一个区的大小,这是因为永远只有一个survivor 区处于可用状态。
持久代中主要存放程序定义的类、方法等,不属于堆(也有人说是一个特殊的堆,不过从jconsole上看,应该是Non-heap memory),不参与GC。
在程序运行过程中,Eden和survivor区的capacity大小在每次执行GC后都可能发生变化。
上图中Virtual区是指,当-Xms的值比-Xmx的值小时,JVM预留的一部分尚未交付给自己使用的内存。
  • 在启动参数中加上 -verbose:gc 可以打印出每次GC释放的空间以及耗时。
  • JVM GC相关参数:
  • -XX:MinHeapFreeRatio=<minimum>  -XX:MaxHeapFreeRatio=<maximum>   -Xms<min>  -Xmx<max> 当某一代的内存超出了Min/MaxHeapFreeRatio的比例时(默认为40%-70%),JVM会自动伸缩该代内存大小以确保在指定比例范围内,但自动伸缩不会超出该代允许的内存大小范围。由于系统默认的-Xmx和-Xmx都比较小,对于服务器程序,强烈建议启动时指明-Xms和-Xmx的值,并且这两个值相等,这样可以避免程序自己决定内存大小带来的开销,当然,如果这个值设置得不合适,JVM就无能为力了。
  • - XX:NewRatio=<3> 指定新生代和年老代在堆内存中的比例(1:3),即新生代占总heap区的1/4。 NewSize 和 MaxNewSize 可用来指定新生代的实际内存大小。
  • -XX:SurvivorRatio=<6> 指定eden区和每个survivor区的比例(1:6),即每个survivor占新生代的1/8(这里感觉有点奇怪,感觉应该是survivor比eden=1:6,但是官方文档这么说: sets the ratio between eden and a survivor space to 1:6 )。一般来说,调节这个参数对性能调优不是太重要。如果survivor区太小,GC时不够用来装来自eden区的live对象,那么这些对象会直接溢出到年老代,如果这个区太大,那么将会浪费掉一部分内存。
垃圾回收器的类别:
  • serial collector 使用单线程来完成GC操作。由于不涉及到线程之间的通信,所以非常高效。如果只有一个CPU核心,或者程序使用的内存不会超过100M时,建议使用这种GC。这种GC不能有效利用多核,当系统只有单核CPU时,JVM会默认使用这类GC。估计现在已经很少见了。
  • parallel collector ( throughput collector ) 在小GC时(新生代GC),可以显著减少GC的开销。在多核或者多线程的硬件环境下,当应用使用的内存为中到大的规模时,应该使用这类GC。当系统有多核的时候,JVM会默认使用这种GC。默认情况下,这类GC仅在小GC时使用多线程,JDK6中,可以使用 -XX:+UseParallelOldGC 的参数来让FULL GC(Old区GC)也使用多线程。使用的线程数等于系统的核数,或者用- XX:ParallelGCThreads=<N> 来指定。由于GC时可能有部分对象从新生代移动到年老代,所以每个GC线程都会预留一定的年老代空间,这样可能会产生年老代碎片,减少GC线程数可以减少这种碎片化的影响,增大年老代空间。
  • concurrent collector 通过牺牲应用性能来缩短GC时的服务停顿。使用 -XX:+UseConcMarkSweepGC 参数打开
垃圾回收器的选择:
  • 如果应用程序占用的内存不超过100M: -XX:+UseSerialGC
  • 如果应用程序运行在单核服务器上并且对应用暂停服务没啥要求:  -XX:+UseSerialGC
  • 如果应用程序的峰值处理能力最重要,并且对应用暂停服务一秒种或者更长时间可以接受:  -XX:+UseParallelGC  -XX:+UseParallelOldGC 此类情况多出现在后台跑的业务中,非用户交互的系统。
  • 如果希望尽量缩短应用程序的暂停响应时间: -XX:+UseConcMarkSweepGC 此类情况较为常见,主要为涉及到用户交互的系统。由于可以通过多台服务负载均衡来弥补性能损失,而且可以保证服务不会在那里傻呆着几秒钟甚至几十秒钟来GC而没反应。
当使用并行GC时,JVM中内存分区和串行不同,如下图:
JVM的下一代G1垃圾回收器会逐渐取代传统的CMS垃圾回收器,但是JDK1.7.2目前还没有使用G1作为默认的垃圾回收器。G1的内存分布和上面的两种分布有非常大的不同,有兴趣的可以去看看。

系统的剩余可用内存空间可能会对垃圾回收性能产生严重影响。我有两台硬件完全相同的服务器,部署完全相同的应用,负载基本相同,但是垃圾回收的性能有本质差别,1台135次FULL GC耗时1分钟,另外一台82次FULL GC耗时34分钟。现在能找到比较明显的不同就是,一台剩余物理内存900M左右,另外一台剩余物理内存40M左右,不知道是不是由于这个原因造成了GC性能如此显著的区别。

分享到:
评论

相关推荐

    java垃圾回收机制

    详细描述讲解了java的垃圾回收机制

    JAVA垃圾回收机制

    垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机制并未改变。垃圾收集的目的在于清除不再...

    Java垃圾回收机制

    Java垃圾回收机制的详细介绍,调理比较清晰,个人进行的总结。

    Java垃圾回收机制详解和调优.doc

    Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收...

    Java中类的生命周期与java垃圾回收机制

    Java中类的生命周期与java垃圾回收机制

    【Java面试题】Java垃圾回收机制

    【Java面试题】Java垃圾回收机制

    java 垃圾回收 机制详解

    说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物。经过半个世纪的发展,内存的动态分配与内存回收技术已经相当成熟,一切看起来都进入了“自动化”时代,那为什么我们还要去...

    Java垃圾回收机制总结

    Java垃圾回收机制总结

    java垃圾回收机制简述

    此文档详细介绍了java回收机制的工作原理、工作过程,以及在程序中使用的一些注意事项

    java垃圾回收器代码举例

    java垃圾回收器机制,代码举例注释及个人笔记

    Java垃圾回收机制的学习和使用

    Java垃圾回收机制的学习和使用Java垃圾回收机制的学习和使用Java垃圾回收机制的学习和使用

    深入Java核心_探秘Java垃圾回收机制

    深入Java核心_探秘Java垃圾回收机制 深入Java核心_探秘Java垃圾回收机制

    Java垃圾回收机制和内存分配

    你认真演示了一遍,你就能明白JAVA的垃圾回收机制。当然文档写的不一定全面,比如文档当中关于老年区少年区有一页写的不是很完整,我也没有添加太多进去,但是还是很有很全面很有参考意义的。

    深入了解Java垃圾回收机制

    Azul Systems CTO & co-Founder, Gil Tene 在SpringOne2GX 2012大会上发表的演讲资料,全面深入地阐述Java垃圾回收的四种机制。并介绍了当今世界上性能与吞吐量最高的JVM产品Zing JVM。 如果希望深入了解Java的垃圾...

    Java垃圾回收机制详解

    Java垃圾回收机制详解!! GC详解!!

    java 垃圾回收机制详细介绍

    垃圾收集器是Java语言区别于其他程序设计语言的一大特色。它把程序员从手工回收内存空间的繁重工作中解脱了出来。在SUN公司的Java程序员(Java Programmer)认证考试中,垃圾收集器是必考的内容,一般最多可以占总...

Global site tag (gtag.js) - Google Analytics