继上次的内存调优分析后(参考[url] http://dmouse.iteye.com/blog/1264118[/url]),gc导致服务器不稳定的情况依然存在,以下记录了后续的调优和分析过程
目前线上有较多的 "Unloading class sun.reflect.GeneratedSerializationConstructorAccessor"、“promotion failed”、“concurrent mode failure”的错误、
关于这三个错误产生的原因,可以参考如下文章
http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
http://blogs.oracle.com/jonthecollector/entry/when_the_sum_of_the
http://blogs.oracle.com/jonthecollector/entry/what_the_heck_s_a
综上所述,原因大概概括如下:
1、tenured的预留空间太小
2、young的一次回收的内存空间太大,以致于tenured无法一次分配连续的内存空间来满足需求
3、tenured的空闲内存空间不连续,碎片较多
目前线上系统虽然采用了较多的tenured的空间预留、采用了tenured的内存空间压缩,但仍然不定期的会出现较多的上述三种error,怀疑和设置空间压缩的参数有关
-XX:CMSFullGCsBeforeCompaction=0
这个参数,指定进行多少次fullGC之后,进行tenured的内存空间压缩,对 0 的理解认为是每次都会,建议设置为1进行管产
-XX:CMSFullGCsBeforeCompaction=1
目前每台服务器的上述三种error记录数如下
"Unloading class" "promotion failed" "concurrent mode failure"
50----------------------- 2233------------------------8-----------------------------------40
51 -----------------------2544------------------------15----------------------------------62
61_CPS----------------2698------------------------21---------------------------------31
61_CPS2---------------2573-----------------------17---------------------------------40
62_CPS----------------4815------------------------33---------------------------------47
62_CPS2--------------3608------------------------29---------------------------------183
分析内存回收日志,调整了-XX:CMSFullGCsBeforeCompaction=1参数后,回收稳定,无新增的 "Unloading class sun.reflect.GeneratedSerializationConstructorAccessor"、“promotion failed”、“concurrent mode failure”的错误
在JDK 6的HotSpot VM中,Oracle/Sun有官方支持的GC只有CMS比较特殊:其它几种GC的每个周期都是完全stop-the-world的;而CMS的每个并发GC周期则有两个stop-the-world阶段——initial mark与final re-mark,其它阶段是与应用程序一起并发执行的。
所以可以通过监控"initial-mark" 和 ‘remark’ 的时间,来反映因为gc导致的程序中断问题
-Xms3g -Xmx3g -Xmn1g -XX:PermSize=128M -XX:+PrintGCDetails -XX:+UseParNewGC -XX:ParallelGCThreads=8 -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=30 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=1
按照目前配置,线上环境jvm垃圾回收效率提升,线程中断情况和中断时间明显减少
-Xms3g -Xmx3g -Xmn1g (堆最大内存 堆最小内存 新生代最大内存)
1、建议按照系统环境尽量设置合理的值
2、建议最大内存和最小内存尽量保持一致;jvm会动态分配内存,为了减少内存临时吃紧造成的重新分配开销,提高内存分配的稳定性;-Xms和-Xmx 默认为物理内存的1/64
3、建议尽量将新生代内存设置为较符合系统的值,避免过小的设置;新生代内存 = eden+ 2 survivor space;Sun官方推荐配置为整个堆的3/8
-XX:PermSize=128M (永久带内存大小)
1、存放编译后class对象的地方,默认物理内存的1/64,建议按照系统实际情况设置
-XX:+PrintGCDetails (打印gc详细信息)
形式诸如
[GC [ParNew: 839977K->1563K(943744K), 0.0048690 secs] 994555K->156183K(3040896K), 0.0052340 secs] [Times: user=0.02 sys=0.01, real=0.01 secs]
[GC [1 CMS-initial-mark: 629255K(2097152K)] 631951K(3040896K), 0.0066920 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[CMS-concurrent-mark: 1.385/1.385 secs] [Times: user=4.80 sys=0.29, real=1.38 secs]
[CMS-concurrent-preclean: 0.008/0.008 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC [ParNew: 840863K->2737K(943744K), 0.0079350 secs] 1470119K->632187K(3040896K), 0.0084240 secs] [Times: user=0.03 sys=0.01, real=
0.01 secs]
[CMS-concurrent-abortable-preclean: 0.646/1.471 secs] [Times: user=2.48 sys=0.27, real=1.47 secs]
[GC[YG occupancy: 424421 K (943744 K)][Rescan (parallel) , 0.0519000 secs][weak refs processing, 0.0017730 secs] [1 CMS-remark: 6294
50K(2097152K)] 1053871K(3040896K), 0.0538830 secs] [Times: user=0.32 sys=0.01, real=0.05 secs]
[CMS-concurrent-sweep: 0.971/0.971 secs] [Times: user=2.06 sys=0.19, real=0.97 secs]
[CMS-concurrent-reset: 0.012/0.012 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
具体内容解释详见 http://blogs.oracle.com/poonam/entry/understanding_cms_gc_logs
-XX:+UseParNewGC -XX:ParallelGCThreads=8 -XX:+UseConcMarkSweepGC (年轻代并行回收 收集器并行8个线程 年老代并发回收)
1、建议年轻代使用并行回收,同时按照操作系统processer的个数设置并行线程数,理论上<=操作系统processer个数
2、建议年老代使用并发回收,并发回收以降低中断次数,减少中断时间为目标,适用于对系统响应时间有较高要求的服务
-XX:CMSInitiatingOccupancyFraction=30 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=1
对年老代并发回收的参数优化
1、 -XX:CMSInitiatingOccupancyFraction=30
预留足够的空间给young gc,防止从young gc 过来一个较大的内存块,而年老代无足够预留空间,无法提供内存快用于回收后的分配,引起强制的full gc,造成较长时间的线程中断
2、-XX:+UseCMSCompactAtFullCollection
设置在FULL GC的时候, 对年老代的压缩;CMS是不会移动内存的, 因此, 这个非常容易产生碎片, 导致内存不够用, 因此, 内存的压缩这个时候就会被启用。 增加这个参数是个好习惯。可能会影响性能,但是可以消除碎片
3、 -XX:CMSFullGCsBeforeCompaction=1
设置多少次full gc后进行内存压缩,由于并发收集器不对内存空间进行压缩,整理,所以运行一段时间以后会产生"碎片",使得运行效率降低.此值设置运行多少次GC以后对内存空间进行压缩,整理。
分享到:
相关推荐
标题中提到了JVM原理、JVM调优、JVM内存模型和JAVA并发,这些都是Java虚拟机(JVM)相关的核心概念。JVM是运行Java字节码的虚拟计算机,为Java提供了一个跨平台的环境,确保Java程序可以在不同的操作系统上运行而...
JVM调优是一个持续的过程,需要根据应用的具体情况进行调整。上述参数只是起点,还需要通过监控工具(如JVisualVM或JConsole)分析GC日志,观察不同GC策略对应用程序的影响,以及内存使用、吞吐量、停顿时间等指标。...
### JVM性能调优——JVM内存管理与GC回收详解 #### 概览 在现代软件开发领域,Java凭借其强大的跨平台能力和丰富的生态系统成为企业级应用的首选语言之一。然而,随着应用程序复杂度的提高以及业务需求的变化,...
3. **内存配置与GC频率**:通过调整JVM内存参数,避免频繁的GC,同时根据计算结果决定合适的机器配置和部署数量。 接下来,我们探讨一些常见的JVM参数配置: 1. **垃圾回收器选择**:根据应用特性选择合适的GC收集...
在调优过程中,我们面临的挑战之一是如何选择合适的垃圾收集算法,以适应不同的应用场景。选择算法时需要考虑应用的特点,例如对象的生命周期分布、内存使用模式以及停顿时间的要求等。 垃圾回收的瓶颈主要体现在两...
- **复制算法**(Copying):将内存分为大小相等的两块,每次只使用其中一块,在垃圾回收时,将还活着的对象复制到另一块上面,然后再把已使用过的内存空间一次清理掉。这种算法适用于新生代,因为每次回收都有大量...
- **青年代(Young Generation)**:大部分对象在这里创建并快速死亡,经历一次或几次Minor GC后,存活对象晋升至老年代。 - **老年代(Old Generation)**:长期存活的对象,经历了多次Minor GC后,它们被移动...
Java虚拟机(JVM)是Java程序运行的基础,它的性能调优对于提升应用程序的...然而,实际调优过程中需要根据应用程序的具体情况进行,包括但不限于对象生命周期、内存分配模式、负载情况等因素,进行细致的测试和分析。
2. jmap -histo:live <pid>:此命令用于查看当前存活的实例,执行过程中可能会触发一次Full GC。 当需要对JVM进行内存溢出处理时,可以通过两个参数来实现自动导出堆内存信息。这两个参数为: 1. -XX:+...
1. **堆内存调优**: - `-Xms` 和 `-Xmx`:分别设置初始堆大小和最大堆大小,确保不会因为内存不足导致系统崩溃。 - `-XX:NewRatio`:设定新生代与老年代的比例,影响垃圾回收策略。 - `-XX:SurvivorRatio`:...
5. 经过第一次Minor GC后仍然存活的对象会被移动到Survivor区,并且每次GC后年龄+1。 6. 当对象年龄达到一定阈值时,会被移至老年代。 #### 五、年轻代中的GC 在年轻代中,JVM需要确保To Survivor空间为空。在每次...
调优过程中,我们需要关注以下指标: - **GC频率**:过高可能意味着内存分配不合理或存在内存泄漏。 - **暂停时间(Pause Time)**:长时间的GC暂停会影响用户体验,应尽可能降低。 - **吞吐量(Throughput)**:...
JVM调优是一个复杂而细致的过程,涉及对内存管理、垃圾回收等多个方面的综合考量。理解不同的垃圾回收算法及其适用场景是提高Java应用程序性能的关键。通过合理选择和配置垃圾回收器,可以显著提升系统的响应速度和...
### JVM内存模型详解 #### 1. 方法区 方法区主要存储类的信息、常量、静态变量等数据。这些数据通常在类加载时创建,并且在整个JVM生命周期中保持不变。对于HotSpot虚拟机而言,这部分区域被称为“永久代”(Perm...
- **Survivor区**:通常被分为From和To两个子区,用于保存经历过至少一次垃圾回收但仍存活的对象。当对象在Survivor区中存活足够次数后,它们会被转移到老年代。 #### 对象的创建、分配与访问 对象的创建主要通过...
总之,JVM调优是一个涉及多方面因素的复杂过程,需要综合考虑应用特性和系统资源,通过调整各种参数来达到最优的运行效果。"JVM调优示例2"为我们提供了一个实践的场景,通过学习和实践,我们可以提升Java应用的性能...
在对Java虚拟机(JVM)进行调优的过程中,我们首先需要理解JVM内存的工作原理以及各个内存区域的作用。JVM内存管理是整个Java应用程序性能优化的重要部分,它涉及对内存的分配、使用和回收的精细控制。 JVM内存可以...
了解JVM内存布局和垃圾回收算法对于进行性能调优和故障排除至关重要。 JVM内存布局通常分为几个部分,包括堆(Heap)、栈(Stack)、方法区(Method Area)、程序计数器(Program Counter)和本地方法栈(Native ...