`
phoenix520
  • 浏览: 142251 次
  • 性别: 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垃圾回收机制(GC)是Java编程语言的关键特性,它自动管理内存,释放不再使用的对象,以防止内存泄漏。GC的运作方式主要有两种策略:引用计数和对象引用遍历。 引用计数是一种简单但不完美的方法。每个对象都有...

    Java垃圾回收机制

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

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

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

    java垃圾回收器代码举例

    Java垃圾回收器(Garbage Collector, GC)是Java编程语言中的一个重要特性,它负责自动管理内存,自动回收不再使用的对象,以防止内存泄漏。在Java中,程序员无需手动释放内存,这一过程由JVM(Java虚拟机)自动完成...

    Java垃圾回收机制总结

    Java垃圾回收机制总结 Java垃圾回收机制是Java虚拟机(JVM)中的一种机制,用于防止内存泄露和有效地使用空闲的内存。垃圾回收机制的主要目的是为了回收无用的对象占用的内存空间,使该空间可被程序再次使用。 ...

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

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

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

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

    细述 Java垃圾回收机制→Java Garbage Collection Introduction - Android 1

    Java垃圾回收机制简介 Java垃圾回收机制是Java语言中的一种自动内存管理机制,它可以帮助程序员更好地编写Java应用程序,而不需要手动编写垃圾回收相关的代码。这篇文章将会介绍Java垃圾回收机制的基本概念和原理,...

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

    Java垃圾回收机制是Java编程中至关重要的一部分,它自动管理内存,释放不再使用的对象,避免内存泄漏,并优化内存使用。Java虚拟机(JVM)的堆内存是存放对象的主要区域,当对象通过new等指令创建后,垃圾回收机制...

    细述 Java垃圾回收机制→How Java Garbage Collection Works- - Android 1

    本文将详细介绍Java垃圾回收机制的工作原理、各个阶段的执行过程、不同的垃圾回收器类型、Java中的引用类型等。 Java垃圾回收机制的工作原理 ------------------------- Java垃圾回收机制的工作原理是,当一个对象...

    浅谈JAVA垃圾回收机制.pdf

    Java 中的垃圾回收机制通过各种算法和垃圾回收器来对可回收对象进行回收,提高了 Java 语言的开发效率和代码的可靠性。 在 Java 中,垃圾回收机制的引入可以避免代码运行时,由于忘记释放对象而带来的内存泄漏问题...

Global site tag (gtag.js) - Google Analytics