转载自:http://yuquan-nana.iteye.com/blog/600369
垃圾收集策略配置
3.1 吞吐量优先
吞吐量是指GC的时间与运行总时间的比值,比如系统运行了100分钟,而GC占用了一分钟,那么吞吐量就是99%,吞吐量优先一般运用于对响应性要求不高的场合,比如web应用,因为网络传输本来就有延迟的问题,GC造成的短暂的暂停使得用户以为是网络阻塞所致。
吞吐量优先可以通过-XX:GCTimeRatio来指定。
当通过-XX:GCTimeRatio不能满足系统的要求以后,我们可以更加细致的来对JVM进行调优。
首先因为要求高吞吐量,这样就需要一个较大的Young generation,此时就需要引入“Parallel scavenging Collector”,可以通过参数:-XX:UseParallelGC来配置。
java -server -Xms3072m -Xmx3072m -XX:NewSize=2560m -XX:MaxNewSize=2560 XX:SurvivorRatio=2 -XX:+UseParallelGC
当年轻代使用了"Parallel scavenge collector"后,老生代就不能使用"CMS"GC了,在JDK1.6之前,此时老生代只能采用串行收集,而JDK1.6引入了并行版本的老生代收集器,可以用参数-XX:UseParallelOldGC来配置。
3.1.1 控制并行的线程数
缺省情况下,Parallel scavenging Collector 会开启与cpu数量相同的线程进行并行的收集,但是也可以调节并行的线程数。假如你想用4个并行的线程去收集Young generation的话,那么就可以配置-XX:ParallelGCThreads=4,此时JVM的配置参数如下:
java -server -Xms3072m -Xmx3072m -XX:NewSize=2560m -XX:MaxNewSize=2560 XX:SurvivorRatio=2 -XX:+UseParallelGC -XX:ParallelGCThreads=4
3.1.2 自动调节新生代
在采用了"Parallel scavenge collector"后,此GC会根据运行时的情况自动调节survivor ratio来使得性能最优,因此"Parallel scavenge collector"应该总是开启此参数。
此时JVM的参数配置如下:
java -server -Xms3072m -Xmx3072m -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:+UseAdaptiveSizePolicy
3.2 响应时间优先
响应时间优先是指GC每次运行的时间不能太久,这种情况一般使用与对及时性要求很高的系统,比如股票系统等。
响应时间优先可以通过参数-XX:MaxGCPauseMillis来配置,配置以后JVM将会自动调节年轻代,老生代的内存分配来满足参数设置。
在一般情况下,JVM的默认配置就可以满足要求,只有默认配置不能满足系统的要求时候,才会根据具体的情况来对JVM进行性能调优。如果采用默认的配置不能满足系统的要求,那么此时就可以自己动手来调节。
此时"Young generation"可以采用"Parallel copying collector",而"Old generation"则可以采用"Concurrent Collector",
举个例子来说,以下参数设置了新生代用Parallel Copying Collector,老生代采用CMS收集器。
java -server -Xms512m -Xmx512m -XX:NewSize=64m -XX:MaxNewSize=64m -XX:SurvivorRatio=2 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
此时需要注意两个问题:
1 如果没有指定-XX:+UseParNewGC,则采用默认的非并行版本的copy collector.
2 如果在一个单CPU的系统上设置了-XX:+UseParNewGC ,则默认还是采用缺省的copy collector.
3.2.1 控制并行的线程数
默认情况下,Parallel copy collector启动和CPU数量一样的线程,也可以通过参数-XX:ParallelGCThreads来指定,比如你想用3个线程去进行并发的复制收集,那么可以改变上述参数如下:
java -server -Xms512m -Xmx512m -XX:NewSize=64m -XX:MaxNewSize=64m -XX:SurvivorRatio=2 -XX:ParallelGCThreads=4 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
3.2.2 控制并发收集的临界值
默认情况下,CMS gc在"old generation"空间占用率高于68%的时候,就会进行垃圾收集,而如果想控制收集的临界值,可以通过参数:-XX:CMSInitiatingOccupancyFraction来控制,比如改变上述的JVM配置如下:
java -server -Xms512m -Xmx512m -XX:NewSize=64m -XX:MaxNewSize=64m -XX:SurvivorRatio=2 -XX:ParallelGCThreads=4 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:CMSInitiatingOccupancyFraction=35
四 GC触发以及常见的内存错误
4.1 Minor GC的触发
Minor GC主要负责收集Young Generation,Minor GC一般在新生代不够用的情况下触发,比如我们一次性创建了很多对象等。
List<byte[]> buffer = new ArrayList<byte[]>(); for(int i=0;i<8*1024;i++){
buffer.add(new byte[1024]);
}
以上代码通过一个字节数组的List模拟触发Minor gc,设置JVM参数如下:
-verbose:gc -Xmn10M -Xms64M -Xmx64M -XX:+PrintGC
设置以上参数以后,因为-Xmn=10M,默认-XX:SurvivorRatio=8 ,则eden的空间大小为8M,当eden对象大小超过8M的时候就会触发Minor gc.
运行的结果如下:
[GC 8192K->8030K(64512K), 0.0243391 secs]
从运行结果可以看出,gc前和gc后的eden区的占用情况,需要注意的是括号里(64512)这个数值时63M,它不包括一块Survivor 空间。
这里需要注意的一点就是,如果创建的对象大于eden的大小,那么将不会通过Survivor空间复制,直接转移到old generation.
调整以上代码如下:
List<byte[]> buffer = new ArrayList<byte[]>();
buffer.add(new byte[8*1024*1024]);
通过同样的JVM参数运行,则发现不会触发Minor gc,这是因为对象超过了eden的大小,从而直接分配到了Old generation.
4.2 Major GC的触发
4.2.1 Old Generation空间满或者接近某一个比例
Old generation 空间满是因为Young generation提升到Old generation的对象+Old generation的本来的大小已经接近或者超过了Old generation的大小。对于CMS GC,当Old generation空间使用率接近某一个比例,可以通过参数-XX:CMS InitialingOccupancyFraction,此参数表示Old generation的使用率,默认为68%。
Young generation对象提升到Old generation对象有以下三种情况:
Ø 分配的对象大于eden空间的大小
Ø 在Young generation代中经过了-XX:MaxTenuringThreshold次复制任然存活的对象
Ø Minor gc的时候,放不进to survivor的对象
当Major GC以后,如果还没有足够的空间可以用的话,此时就会抛出java.lang.OutOfMemory:java heap space,当出现此错误的时候,说明可能存在内存泄露现象的,这时候就需要我们对程序进行检查看看什么地方存在内存泄露的。
我们可以通过以下代码来模拟一下java.lang.OutOfMemory:java heap space的发生:
List<byte[]> buffer = new ArrayList<byte[]>();
buffer.add(new byte[10*1024*1024]);
以上代码分配了一个10M的字节数组,我们通过以下的参数运行:
-verbose:gc -Xmn10M -Xms20M -Xmx20M -XX:+PrintGC
以上参数指定Young generation的空间大小为10M,Old generation空间大小为10M。
运行结果如下:
[GC 327K->134K(19456K), 0.0056516 secs]
[Full GC 134K->134K(19456K), 0.0178891 secs]
[Full GC 134K->131K(19456K), 0.0141412 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at Test.main(Test.java:30)
从运行结果可以看出,JVM进行了一次Minor gc和两次的Major gc,从Major gc的输出可以看出,gc以后old区使用率为134K,而字节数组为10M,加起来大于了old generation的空间,所以抛出了异常,如果调整-Xms21M,-Xmx21M,那么就不会触发gc操作也不会出现异常了。
4.2.2 Perm Generation 空间满
Perm Generation空间主要存放Class对象,Field,Method对象,当一次性加载太多的类或者在热部署以后不卸载类的情况(比如在Jboss服务器中,如果经常热部署一些应用就会出现Perm 空间溢出)就会造成Perm Generation被占满,此时就会出现:
java.lang.OutOfMemory:PermGen space,在出现此异常的时候,如果是因为热部署引起的,我们重新启动AS就可以了,如果是因为加载的类太多,此时可以通过-XX:PermSize和-XX:MaxPermSize调整。
4.3 常见内存错误分析
4.3.1 StackOverflowError
java.lang.StackOverflowError错误表示JVM栈溢出,出现这个错误的原因一般都是递归的层次太深,或者无限的递归造成的。出现这种错误的时候首先要对应用程序进行检查,看看是那些代码造成了栈溢出,如果是递归造成的可以改为迭代方式实现。
JVM同样也提供了一个参数来让我们调节运行时栈空间的大小。-XX:Xss=256K表示栈空间最大为256K.我们也可以调大,但是建议不要对此参数进行调节。
4.3.2 OutOfMemoryError: Java heap space.
java.lang.OutOfMemoryError: Java heap space这个错误表示JVM的新生代和老生代的内存不足。出现这个错误说明应用程序出现了内存溢出或者程序所需要的内存大于JVM的内存设置了。
遇到这个问题的时候,首先我们可以调节JVM的Heap内存的大小,具体可以通过-Xmx -Xms来进行设置,如果设置大以后还是会出现内存溢出,那么说明应用程序本身存在内存泄露,这个时候就需要我们对应用程序进行检查,找出导致内存泄露的地方,然后修正。
4.3.3 OutOfMemory:PermGen space
java.lang.OutOfMemory:PermGen space错误是由Perm space空间不足。一般出现这个错误是由加载了太多的类或者大量使用了动态代理造成的。如果出现了这个错误,我们可以将Perm空间调大一点。
-XX:PermSize=16M -XX:MaxPermSize=64M
参考资料
1 http://developers.sun.com/mobility/midp/articles/garbage/
2 http://developers.sun.com/mobility/midp/articles/garbagecollection2/
3 http://blogs.sun.com/watt/resource/jvm-options-list.html
4 http://java.sun.com/developer/technicalArticles/Programming/turbo/
5 http://www.ibm.com/developerworks/library/j-jtp10283/index.html?S_TACT=105AGX52&S_CMP=cn-a-j
6 http://www.ibm.com/developerworks/library/j-jtp11253/index.html?S_TACT=105AGX52&S_CMP=cn-a-j
分享到:
相关推荐
Java虚拟机(JVM)内存模型是Java程序运行的基础,它包括了多个关键的内存区域。...开发者需要根据应用特点调整内存参数,选择合适的垃圾收集策略,以避免内存溢出、提高系统效率并确保程序的稳定运行。
G1垃圾收集器是Java虚拟机(JVM)的一部分,它引入了区域(Region)的概念,将堆内存划分为多个固定大小的区域,并采用分代收集策略。 在G1收集器的工作流程中,区域可以被分为新生代(Young Generation)、老年代...
Java虚拟机(JVM)是运行Java程序的核心环境,它负责解释执行Java...了解这些垃圾收集器和算法是深入理解Java虚拟机性能优化的基础,有助于开发者更有效地编写Java代码和配置虚拟机参数,从而提升应用的性能和稳定性。
### 性能工程师指南:玩转OpenJDK HotSpot垃圾收集器 ...特别是在Java应用中,合理配置和优化JVM的垃圾收集器是提高系统性能的关键之一。通过对GC的深入理解以及合理的调优策略,可以显著提升Java应用的整体性能表现。
- 区域针对性收运:根据区域特性制定不同的收集策略,如人群密集区、店铺、夜市、市场和无主垃圾的处理,以提高收集效率和环境卫生。 - “阳光督导队”:培训保洁员成为文明行为宣传员,通过劝导提高市民环保意识...
这些信息对于确定垃圾的分类收集策略和处理方式具有指导意义。 2. **垃圾成分变化趋势**:随着生活水平的提高和环保意识的增强,有机物含量可能增加,无机物比例降低,可回收物的含量也会逐年上升。因此,设计时需...
Java垃圾收集与异常处理是Java编程中至关重要的概念,它们对于程序的稳定性和性能有着...在实际开发中,结合具体的业务需求和系统特性,选择合适的垃圾收集器配置和异常处理策略,对于提升系统性能和稳定性至关重要。
Java垃圾收集概述主要关注的是Java...开发者需要了解不同类型的垃圾收集器及其特性,以便根据应用的具体需求选择合适的配置,同时通过合理设计数据结构和算法,减少不必要的内存开销,降低垃圾收集对应用运行的影响。
本方案旨在提供一种高效、环保且规范的垃圾收集运输策略,确保垃圾不露天储存,不露天收集运输,以提升城市整体卫生水平。 首先,垃圾收集运输需配备专业的垃圾运输车辆,以满足垃圾清运的需求。在这个方案中,公司...
针对不同区域的特点,采取定制化的垃圾收集策略。例如,对于人群密集的场所,增加清理频率,可能的话,改进垃圾设施以减少二次污染。对于店铺,通过沟通确定收集时间和路线,提供上门服务。对于夜市和市场,考虑到其...
垃圾前端收集运输管理方案是一项多方面的管理策略,旨在规范垃圾收集、运输、处理的整个过程,以保护环境、提高生活质量和城市美誉度。本文将从设备、设施要求、管理要求、信息要求、垃圾投放、工具配置等多方面讨论...
【JVM垃圾收集器概述】 ...选择合适的垃圾收集器配置,结合不同年代的内存管理策略,可以有效避免内存溢出,提高系统响应速度。在面试中,展示对这些知识点的掌握将有助于展示自己的专业技能和解决问题的能力。
垃圾收集器的性能和效率对于Java应用的性能至关重要,因此开发者需要对这些垃圾收集策略有深入的理解。在实际应用中,垃圾收集的配置和监控也是保证系统稳定运行的关键环节。随着JVM技术的不断发展,垃圾收集算法和...
- **默认选择**:JVM默认选择的垃圾收集器和堆配置通常是基于平台和应用需求自动设定的,但可以通过参数进行调整。 - **基于行为的调整**:垃圾收集器的调整不仅关注性能,也关注应用程序的响应时间和用户体验。...
不同的垃圾收集算法会针对这些阶段采用不同的策略。 3. **可达性分析**:垃圾收集器通过可达性分析来确定哪些对象是可访问的,哪些是垃圾。如果一个对象可以从根集合(如全局变量、活动线程栈、JNI引用等)到达,...
7. **内存配置与调优**:开发者可以通过设置JVM参数来调整堆大小、垃圾收集器类型以及各种性能相关的策略,以适应不同应用的需求。例如, `-Xms` 和 `-Xmx` 分别用于设置初始堆大小和最大堆大小。 总的来说,Java的...