JVM调优案例分析与实战

本文深入分析了JVM中的内存溢出问题,包括堆内存、栈、运行时常量池和方法区溢出的模拟及日志解读。通过实际案例探讨了速度调优策略,如JVM参数设置、GC优化,并分享了CMS垃圾收集器的使用经验。在QA部分,解答了关于CMS与Full GC的关系以及并发模式失败后的处理机制。
摘要由CSDN通过智能技术生成

一、内存溢出

1、堆内存溢出

模拟代码以及JVM设置:

public  class  OOMTest {
     //JVM设置
     //-Xms30M -Xmx30M -Xmn10M -XX:+PrintGCDetails -XX:PermSize=10m -XX:MaxPermSize=10m -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError
     static  class  OOMObject {
     }
 
     public  static  void  main(String[] args) {
         List<OOMObject> list =  new  ArrayList<OOMObject>();
 
         while  ( true ) {
             list.add( new  OOMObject());
         }
     }
}

预备知识——CMS清理过程:

CMS的gc日志分为一下几个步骤,重点关注initial-mark和remark这两个阶段,因为这两个阶段会stop进程。
初始标记(init mark):收集根引用,这是一个stop-the-world阶段。
并发标记(concurrent mark):这个阶段可以和用户应用并发进行。遍历老年代的对象图,标记出活着的对象。
并发预清理(concurrent preclean):这同样是一个并发的阶段。主要的用途也是用来标记,用来标记那些在前面标记之后,

                                                             发生变化的引用。主要是为了缩短remark阶段的stop-the-world的时间。

重新标记(remark):这是一个stop-the-world的操作。暂停各个应用,统计那些在发生变化的标记。
并发清理(concurrent sweep):并发扫描整个老年代,回收一些在对象图中不可达对象所占用的空间。
并发重置(concurrent reset):重置某些数据结果,以备下一个回收周期

运行日志解读:

[GC [ParNew: 7936K->1024K(9216K),  0.0351710  secs] 7936K->5613K(29696K),  0.0352000  secs] [Times: user= 0.14  sys= 0.02 , real= 0.03  secs]
[GC [ParNew: 9216K->1024K(9216K),  0.0136330  secs] 13805K->12213K(29696K),  0.0136510  secs] [Times: user= 0.07  sys= 0.00 , real= 0.02  secs]
[GC [ 1  CMS-initial-mark: 11189K(20480K)] 12330K(29696K),  0.0018950  secs] [Times: user= 0.00  sys= 0.00 , real= 0.00  secs]
[GC [ParNew (promotion failed): 9216K->9216K(9216K),  2.2553270  secs][CMS[CMS-concurrent-mark:  0.035 / 2.290  secs] [Times: user= 2.84  sys= 0.75 , real= 2.29  secs]
  (concurrent mode failure): 19558K->20479K(20480K),  0.1047330  secs] 20405K->21027K(29696K), [CMS Perm : 3055K->3053K(10240K)],  2.3601020  secs] [Times: user= 2.90  sys= 0.75 , real= 2.36  secs]
[Full GC [CMS: 20479K->19878K(20480K),  0.0880600  secs] 29695K->26772K(29696K), [CMS Perm : 3056K->3056K(10240K)],  0.0880850  secs] [Times: user= 0.09  sys= 0.00 , real= 0.09  secs]
[GC [ 1  CMS-initial-mark: 19878K(20480K)] 26863K(29696K),  0.0080270  secs] [Times: user= 0.01  sys= 0.00 , real= 0.01  secs]
[Full GC [CMS[CMS-concurrent-mark:  0.026 / 0.037  secs] [Times: user= 0.07  sys= 0.01 , real= 0.04  secs]
  (concurrent mode failure): 20479K->20476K(20480K),  0.1131200  secs] 29695K->29608K(29696K), [CMS Perm : 3056K->3056K(10240K)],  0.1131460  secs] [Times: user= 0.13  sys= 0.00 , real= 0.11  secs]
[Full GC [CMS: 20479K->20447K(20480K),  0.0847510  secs] 29695K->29663K(29696K), [CMS Perm : 3056K->3056K(10240K)],  0.0847740  secs] [Times: user= 0.09  sys= 0.00 , real= 0.09  secs]
[GC [ 1  CMS-initial-mark: 20447K(20480K)] 29663K(29696K),  0.0099760  secs] [Times: user= 0.01  sys= 0.00 , real= 0.01  secs]
[Full GC [CMS[CMS-concurrent-mark:  0.026 / 0.028  secs] [Times: user= 0.05  sys= 0.00 , real= 0.03  secs]
  (concurrent mode failure): 20479K->20479K(20480K),  0.0951170  secs] 29695K->29695K(29696K), [CMS Perm : 3056K->3056K(10240K)],  0.0951400  secs] [Times: user= 0.12  sys= 0.00 , real= 0.10  secs]
[Full GC [CMS: 20479K->20479K(20480K),  0.0661090  secs] 29695K->29695K(29696K), [CMS Perm : 3056K->3056K(10240K)],  0.0661430  secs] [Times: user= 0.06  sys= 0.00 , real= 0.06  secs]
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid88950.hprof ...
Heap dump file created [ 39331031  bytes in  0.273  secs]
[GC [ 1  CMS-initial-mark: 20479K(20480K)] 29695K(29696K),  0.0120230  secs] [Times: user= 0.01  sys= 0.00 , real= 0.02  secs]
[Full GC [CMS[CMS-concurrent-mark:  0.028 / 0.029  secs] [Times: user= 0.05  sys= 0.00 , real= 0.03  secs]
  (concurrent mode failure)Exception in thread  "main"  : 20480K->778K(20480K),  0.0494630  secs] 29695K->778K(29696K), [CMS Perm : 3056K->3056K(10240K)],  0.0494890  secs] [Times: user= 0.07  sys= 0.00 , real= 0.05  secs]
java.lang.OutOfMemoryError: Java heap space
     at jvm.OOMTest.main(OOMTest.java: 25 )
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java: 57 )
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java: 43 )
     at java.lang.reflect.Method.invoke(Method.java: 601 )
     at com.intellij.rt.execution.application.AppMain.main(AppMain.java: 140 )
Heap
  par  new  generation   total 9216K, used 150K [ 0x00000007fd800000 0x00000007fe200000 0x00000007fe200000 )
   eden space 8192K,    1 % used [ 0x00000007fd800000 0x00000007fd8258f8 0x00000007fe000000 )
   from space 1024K,    0 % used [ 0x00000007fe100000 0x00000007fe100000 0x00000007fe200000 )
   to   space 1024K,    0 % used [ 0x00000007fe000000 0x00000007fe000000 0x00000007fe100000 )
  concurrent mark-sweep generation total 20480K, used 778K [ 0x00000007fe200000 0x00000007ff600000 0x00000007ff600000 )
  concurrent-mark-sweep perm gen total 10240K, used 3089K [ 0x00000007ff600000 0x0000000800000000 0x0000000800000000 )
 
 
日志解读:
1 、[GC (Young GC)[ParNew(使用ParNew作为年轻代的垃圾回收期): 7936K(年轻代垃圾回收前的大小)->1024K(年轻代垃圾回收后的大小)(9216K 年轻代容量),  0.0351710  secs(回收时间)] 7936K(整个heap垃圾回收前的大小)->5613K(整个heap垃圾回收后的大小)( 29696 (整个heap容量大小)),  0.0352000  secs(回收时间)] [Times: user= 0.14 (Young GC用户耗时)
sys= 0.02 (系统耗时), real= 0.03  secs(真实耗时)]
2 、[GC [ 1  CMS-initial-mark(初始标记,收集跟引用): 11189K(老年代使用内存)(20480K老年代容量)] 12330K(对内存使用内存)(29696K对内存容量),  0.0018950  secs] [Times: user= 0.00  sys= 0.00 , real= 0.00  secs]
3 、[GC [ParNew (promotion failed一般发生在新生代晋升老年代时,老年代空间不够或连续空间不够却还没达到old区的触发值,引发Full Gc.): 9216K->9216K(9216K),  2.2553270  secs]
4 、[CMS[CMS-concurrent-mark并发标记:  0.035 实际标记时间/ 2.290 总并发标记时间 secs] [Times: user= 2.84  sys= 0.75 , real= 2.29  secs]
5 、(concurrent mode failure一般发生在CMS GC 运行过程中,老年代空间不足,引发Full GC): 19558K->20479K(20480K),  0.1047330  secs] 20405K->21027K(29696K), [CMS Perm : 3055K->3053K(10240K)],  2.3601020  secs] [Times: user= 2.90  sys= 0.75 , real= 2.36  secs]
6 、[Full GC一次Full GC的整体效果[CMS: 20479K->19878K(20480K),  0.0880600  secs] 29695K->26772K(29696K), [CMS Perm : 3056K->3056K(10240K)],  0.0880850  secs] [Times: user= 0.09  sys= 0.00 , real= 0.09  secs]
7 、java.lang.OutOfMemoryError: Java heap space报错信息,堆内存溢出。
8 、Dumping heap to java_pid88950.hprof ...堆内存映像保存文件和大小。
   Heap dump file created [ 39331031  bytes in  0.273  secs]
  

内存快照java_pid88950.hprof分析:

2、栈深度溢出

模拟代码及JVM参数设置:

public  class  JavaStackOverFlowTest {
 
     //-Xms30M -Xmx30M -Xmn10M -XX:+PrintGCDetails -XX:PermSize=2m -XX:MaxPermSize=2m -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError
     private  int  stackLength =  1 ;
 
     public  void  stackLeak() {
         stackLength++;
         stackLeak();
     }
 
     public  static  void  main(String[] args)  throws  Throwable {
         JavaStackOverFlowTest oom =  new  JavaStackOverFlowTest();
         try  {
             oom.stackLeak();
         catch  (Throwable e) {
             System.out.println( "stack length:"  + oom.stackLength);
             throw  e;
         }
     }
}

运行日志:

Exception in thread  "main"  java.lang.StackOverflowError
stack length: 10806
     at jvm.JavaStackOverFlowTest.stackLeak(JavaStackOverFlowTest.java: 20 )
     at jvm.JavaStackOverFlowTest.stackLeak(JavaStackOverFlowTest.java: 21 )
     at jvm.JavaStackOverFlowTest.stackLeak(JavaStackOverFlowTest.java: 21 )
     at jvm.JavaStackOverFlowTest.stackLeak(JavaStackOverFlowTest.java: 21 )
     at jvm.JavaStackOverFlowTest.stackLeak(JavaStackOverFlowTest.java: 21 )
     at jvm.JavaStackOverFlowTest.stackLeak(JavaStackOverFlowTest.java: 21 )

3、运行时常量池内存溢出

模拟代码及JVM参数设置:

public  class  RunConstantOOMTest {
 
     //-Xms30M -Xmx30M -Xmn10M -XX:+PrintGCDetails -XX:PermSize=2m -XX:MaxPermSize=2m -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError
     public  static  void  main(String[] args) {
         // 使用List保持着常量池引用,避免Full GC回收常量池行为
         List<String> list =  new  ArrayList<String>();
         int  i =  0 ;
         while  ( true ) {
             list.add(String.valueOf(i++).intern());
         }
     }
 
}

运行日志以及解读:

[Full GC [CMS: 0K->221K(20480K),  0.0048730  secs] 367K->221K(29696K), [CMS Perm : 2047K->2046K(2048K)],  0.0049090  secs] [Times: user= 0.00  sys= 0.00 , real= 0.01  secs]
[Full GC [CMS: 221K->210K(20480K),  0.0024700  secs] 221K->210K(29696K), [CMS Perm : 2046K->2046K(2048K)],  0.0024890  secs] [Times: user= 0.00  sys= 0.00 , real= 0.00  secs]
java.lang.OutOfMemoryError: PermGen space
Dumping heap to java_pid89325.hprof ...
[Full GC [CMS: 210K->210K(20480K),  0.0020000  secs] 210K->210K(29696K), [CMS Perm : 2046K->2046K(2048K)],  0.0020180  secs] [Times: user= 0.01  sys= 0.00 , real= 0.00  secs]
Heap dump file created [ 553652  bytes in  0.010  secs]
[Full GC [CMS: 210K->210K(20480K),  0.0022670  secs] 210K->210K(29696K), [CMS Perm : 2046K->2026K(2048K)],  0.0022870  secs] [Times: user= 0.00  sys= 0.00 , real= 0.00  secs]
Error occurred during initialization of VM
java.lang.OutOfMemoryError: PermGen space
     at java.util.concurrent.locks.ReentrantLock.<init>(ReentrantLock.java: 262 )
     at java.util.concurrent.ConcurrentHashMap$Segment.<init>(ConcurrentHashMap.java: 425 )
     at java.util.concurrent.ConcurrentHashMap.<init>(ConcurrentHashMap.java: 825 )
     at sun.util.locale.LocaleObjectCache.<init>(LocaleObjectCache.java: 48 )
     at sun.util.locale.LocaleObjectCache.<init>(LocaleObjectCache.java: 44 )
     at java.util.Locale$Cache.<init>(Locale.java: 676 )
     at java.util.Locale$Cache.<init>(Locale.java: 675 )
     at java.util.Locale.<clinit>(Locale.java: 411 )
 
  
1 、java.lang.OutOfMemoryError: PermGen space
    内存溢出,并且指出是Pern控件溢出。

内存快照java_pid89325.hprof分析:

从中可以看出,Perm区引发的Full Gc效果很不明显,并且打印出来的内存映射快照,不包括Perm区的内存。

4、运行时方法区溢出

模拟代码及JVM参数设置:

public  class  MethodAreaOOMTest {
  
     //-Xms30M -Xmx30M -Xmn10M -XX:+PrintGCDetails -XX:PermSize=10m -XX:MaxPermSize=10m -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError
     public  static  void  main(String[] args) {
         while  ( true ) {
             Enhancer enhancer =  new  Enhancer();
             enhancer.setSuperclass(OOMObject. class );
             enhancer.setUseCache( false );
             enhancer.setCallback( new  MethodInterceptor() {
                 public  Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)  throws  Throwable {
                     return  proxy.invokeSuper(obj, args);
                 }
             });
             enhancer.create();
         }
     }
 
     static  class  OOMObject {
 
     }
}

运行是日志分析:

GC [ParNew: 8192K->1023K(9216K),  0.0023860  secs] 8192K->1833K(29696K),  0.0024110  secs] [Times: user= 0.01  sys= 0.01 , real= 0.00  secs]
[GC [ParNew: 9215K->746K(9216K),  0.0048310  secs] 10025K->2498K(29696K),  0.0048490  secs] [Times: user= 0.02  sys= 0.00 , real= 0.01  secs]
[GC [ParNew: 8938K->577K(9216K),  0.0010750  secs] 10690K->2329K(29696K),  0.0010930  secs] [Times: user= 0.01  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 8769K->663K(9216K),  0.0015340  secs] 10521K->2415K(29696K),  0.0015720  secs] [Times: user= 0.01  sys= 0.00 , real= 0.01  secs]
[GC [ParNew: 8855K->661K(9216K),  0.0032120  secs] 10607K->2647K(29696K),  0.0032350  secs] [Times: user= 0.02  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 8853K->953K(9216K),  0.0020750  secs] 10839K->2938K(29696K),  0.0020930  secs] [Times: user= 0.01  sys= 0.00 , real= 0.01  secs]
[GC [ParNew: 9145K->701K(9216K),  0.0014820  secs] 11130K->2851K(29696K),  0.0015030  secs] [Times: user= 0.00  sys= 0.00 , real= 0.01  secs]
[GC [ParNew: 8893K->712K(9216K),  0.0011870  secs] 11043K->2862K(29696K),  0.0012040  secs] [Times: user= 0.01  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 8904K->947K(9216K),  0.0015220  secs] 11054K->3223K(29696K),  0.0015400  secs] [Times: user= 0.01  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 9139K->666K(9216K),  0.0011920  secs] 11415K->3056K(29696K),  0.0012070  secs] [Times: user= 0.00  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 8858K->558K(9216K),  0.0011120  secs] 11248K->3060K(29696K),  0.0011310  secs] [Times: user= 0.01  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 8750K->708K(9216K),  0.0014650  secs] 11252K->3309K(29696K),  0.0014900  secs] [Times: user= 0.01  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 8900K->834K(9216K),  0.0010410  secs] 11501K->3543K(29696K),  0.0010570  secs] [Times: user= 0.01  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 9026K->789K(9216K),  0.0011080  secs] 11735K->3497K(29696K),  0.0011270  secs] [Times: user= 0.00  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 8981K->870K(9216K),  0.0018110  secs] 11689K->3766K(29696K),  0.0018310  secs] [Times: user= 0.00  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 9062K->747K(9216K),  0.0015880  secs] 11958K->3842K(29696K),  0.0016030  secs] [Times: user= 0.01  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 8939K->704K(9216K),  0.0009460  secs] 12034K->3798K(29696K),  0.0009630  secs] [Times: user= 0.00  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 8896K->896K(9216K),  0.0011260  secs] 11990K->4102K(29696K),  0.0011440  secs] [Times: user= 0.01  sys= 0.00 , real= 0.00  secs]
[GC [ParNew: 9088K->823K(9216K),  0.0009460  secs] 12294K->4135K(29696K),  0.0009660  secs] [Times: user= 0.00  sys= 0.00 , real= 0.00  secs]
[Full GC [CMS: 3312K->3044K(20480K),  0.0271780  secs] 4471K->3044K(29696K), [CMS Perm : 10239K->10236K(10240K)],  0.0272090  secs] [Times: user= 0.07  sys= 0.00 , real= 0.03  secs]
[Full GC [CMS: 3044K->3072K(20480K),  0.0181400  secs] 3290K->3072K(29696K), [CMS Perm : 10239K->10239K(10240K)],  0.0181620  secs] [Times: user= 0.02  sys= 0.00 , real= 0.02  secs]
[Full GC [CMS: 3072K->1834K(20480K),  0.0155940  secs] 3072K->1834K(29696K), [CMS Perm : 10239K->10236K(10240K)],  0.0156160  secs] [Times: user= 0.02  sys= 0.00 , real= 0.02  secs]
[Full GC [CMS: 1834K->1842K(20480K),  0.0149900  secs] 2080K->1842K(29696K), [CMS Perm : 10239K->10239K(10240K)],  0.0150120  secs] [Times: user= 0.01  sys= 0.00 , real= 0.01  secs]
[Full GC [CMS: 1842K->1840K(20480K),  0.0132320  secs] 1925K->1840K(29696K), [CMS Perm : 10239K->10239K(10240K)],  0.0132540  secs] [Times: user= 0.02  sys= 0.00 , real= 0.01  secs]
java.lang.OutOfMemoryError: PermGen space
Dumping heap to java_pid89368.hprof ...
Heap dump file created [ 3395371  bytes in  0.033  secs]
[Full GC [CMS: 1840K->1794K(20480K),  0.0127750  secs] 2005K->1794K(29696K), [CMS Perm : 10239K->10237K(10240K)],  0.0128040  secs] [Times: user= 0.01  sys= 0.00 , real= 0.01  secs]
[Full GC [CMS: 1794K->1794K(20480K),  0.0139640  secs] 1794K->1794K(29696K), [CMS Perm : 10237K->10237K(10240K)],  0.0139850  secs] [Times: user= 0.01  sys= 0.00 , real= 0.02  secs]
[Full GC [CMSException in thread  "main"  : 1794K->1782K(20480K),  0.0160820  secs] 1958K->1782K(29696K), [CMS Perm : 10239K->10239K(10240K)],  0.0161040  secs] [Times: user= 0.02  sys= 0.00 , real= 0.01  secs]
[Full GC [CMS: 1782K->1782K(20480K),  0.0138930  secs] 1782K->1782K(29696K), [CMS Perm : 10239K->10239K(10240K)],  0.0139150  secs] [Times: user= 0.01  sys= 0.00 , real= 0.02  secs]
[Full GC [CMS
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread  "main"
: 1782K->1773K(20480K),  0.0158560  secs] 1946K->1773K(29696K), [CMS Perm : 10239K->10238K(10240K)],  0.0158780  secs] [Times: user= 0.02  sys= 0.00 , real= 0.01  secs]
[Full GC [CMS: 1773K->1771K(20480K),  0.0120200  secs] 1856K->1771K(29696K), [CMS Perm : 10238K->10238K(10240K)],  0.0120410  secs] [Times: user= 0.01  sys= 0.00 , real= 0.01  secs]
Heap
  par  new  generation   total 9216K, used 82K [ 0x0000000112ad0000 0x00000001134d0000 0x00000001134d0000 )
   eden space 8192K,    1 % used [ 0x0000000112ad0000 0x0000000112ae4a20 0x00000001132d0000 )
   from space 1024K,    0 % used [ 0x00000001133d0000 0x00000001133d0000 0x00000001134d0000 )
   to   space 1024K,    0 % used [ 0x00000001132d0000 0x00000001132d0000 0x00000001133d0000 )
  concurrent mark-sweep generation total 20480K, used 1771K [ 0x00000001134d0000 0x00000001148d0000 0x00000001148d0000 )
  concurrent-mark-sweep perm gen total 10240K, used 10238K [ 0x00000001148d0000 0x00000001152d0000 0x00000001152d0000 )

和运行时常量池溢出一样,伴随着很多次效果不明显的Full GC,并且Perm区的内存快照不会进行保存。

二、典型案例分析

案例分类
案例分析
案例现象
排查方法
解决方法
JVM堆内存溢出。

1、CMS内存溢出案例。

现象:CMS一段时间不重启或者不发布,一般为两三天,晚上就会报警,报警内

容为Full GC,内存溢出。重启后问题马上就可以恢复。

分析:通过分析内存,发现下面这个类的interfaceMap占用了大部分内存,进而

发现是这个消息消费者线程Deal2Listener占用大部分内存。

结论:监听线程不同于用户请求线程,不会在用户请求结束后主动释放内存,而

会一直存在这个线程,除非重启或者重新部署。而这个监听线程不断往线程缓存

中存入数据,并且垃圾回收期无法进行回收,最终导致堆内存溢出。

2、合作取数据库数据量过大导致堆内存溢出。

 

Full GC次数较多,并伴随着

java.lang.OutOfMemoryError:

Java heap space下面的

报错信息

添加参数-XX:

+HeapDumpOnOutOfMemoryError

找到对应的内存溢出内存快照,

用mat打开对应的内存快照,

来进行快照分析。

保存现场后

重启服务器。

分析内存快照

找到内存

溢出的原因,

修复代码。

Perm区内存溢出。

1、调用的jar包中有String.intern()的调用。

2、groovy脚本导致的FullGC问题

 


jmap -heap 12004查看内存分配情况。

 堆中还有大量的内存未使用,但是不断

进行Full GC并且每次GC效果不明显。


查看permSize大小,看大小是否设置的合适,检查是否有大量的常量设置,检查是否有cglib等反射生成的代码。

代码中或者jar包有显示的String.intern()的调用,修复代码。
直接分配内存溢出

1、产品中心对内存设置过大,导致频繁Full GC。

JVM堆空间分配的内存过大,导致对外内存不够用,系统

不定期抛出内存溢出异常。

 

所有的堆内存和Perm区都压力不大,只有抛出异常时才进行Full GC。

(如果设置了-XX:+DisableExplicitGC开关的话,对中还有很多空闲内存,却不断抛出内存溢出异常)

添加参数-XX:

+HeapDumpOnOutOfMemoryError

无任何内存映像文件产生。

在异常栈中能够找到Unsafe.allocateMemory等字样。

 

 

 检查系统内存和JVM内存,看JVM内存设置的是否合理。

检查-Xss看线程堆栈是否设置的合理。

检查代码中是否有Socket的使用和JNI代码。

JVM线程打满。


4、外部调用超时、数据库连接超时、数据库死锁导致JVM线程打满。

 

系统接口调用出现502、504错误,

并伴随着一定的连接超时报错。

jstat -l 进程号,打印进程中的线程

栈信息,通过查看线程栈信息,找出进程中是否有Block或者Running的线程。

外部接口调用、数据库连接或者处理都有超时控制。

GC导致长时间停顿


5、JVM内存扩容后,不定期出现长时间失去响应的现象。

不定期出现长时间失去响应的现象

查看Full GC记录,发现Full

GC的停顿时间过长

1、调整CMS收集器不设置为吞吐量

优先,或者设置最长停顿时间。

2、若干个虚拟机建立集群来充分利用硬件资源。

三、速度调优

1、类加载和编译时间优化:JDK版本的选择、禁止字节码校验。

2、GC时间优化:JVM初始内存设置、GC收集器选择。

加上-Xint 禁止掉及时编译,总的启动时间从12s上升到了42s。

加上-Dfile.encoding=UTF-8 -Xmx1g -Xmn512m -XX:PermSize=128m -XX:MaxPermSize=128m   进行了3次Full GC。

加上 -Xms1g 后 ,没有进行Full GC。

加上-XX:+UseConcMarkSweepGC,选用虽然进行了16次Full GC,但是停顿时间比较短,看出CMS垃圾收集器的优越性。

参数调优基本都是基于实践,推荐的设置:JVM系列三:JVM参数设置、分析

-Xmx3000M
-Xms3000M
-Xmn600M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-Xss256K
-XX:+DisableExplicitGC
-XX:SurvivorRatio=4
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70
-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps

四、QA

1、Q:CMS是否和Full GC等价?

A:1. Full GC == Major GC指的是对老年代/永久代的stop the world的GC

      2. Full GC的次数 = 老年代GC时 stop the world的次数

     3. Full GC的时间 = 老年代GC时 stop the world的总时间

     4. CMS 不等于Full GC,我们可以看到CMS分为多个阶段,只有stop the world的阶段被计算到了Full GC的次数和时间

         ,而和业务线程并发的GC的次数和时间则不被认为是Full GC

     5. Full GC本身不会先进行Minor GC,我们可以配置,让Full GC之前先进行一次Minor GC,因为老年代很多对象都会引用到新生代的对象,

         先进行一次Minor GC可以提高老年代GC的速度。比如老年代使用CMS时,设置CMSScavengeBeforeRemark优化,让CMS remark之前先进行一次Minor GC。

2、Q:concurrent mode fail失败后,serial old会作为备选搜集器

A:如果并发搜集器不能在年老代填满之前完成不可达(unreachable)对象的回收,或者年老代中有效的空闲内存空间不能满足某一个内存的分配请求

此时应用会被暂停,并在此暂停期间开始垃圾回收,直到回收完成才会恢复应用程序。这种无法并发完成搜集的情况就成为并发模式失败(concurrent mode failure)

在并发模式失败的情况下,serial old会作为备选搜集器,进行一次全局GC(Full GC),因此serial old也算是CMS的“替补”。

显然,由于serial old的介入,会造成较大的停顿时间。

 

参考:

http://www.open-open.com/lib/view/open1432109559864.html

http://blog.csdn.net/historyasamirror/article/details/6245157

http://ifeve.com/jvm-cms-log/

内存溢出异常实战

关于施用full gc频繁的分析及解决

JVM QA经典问答:http://blog.csdn.net/iter_zc/article/details/41802365

GC定义:http://www.tuicool.com/articles/jq2yIza

CMS GC MODE : http://blog.csdn.net/g7n3f/article/details/50828793

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值