poptest是国内惟一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工做为目标。若是对课程感兴趣,请你们咨询qq:908821478,咨询电话010-84505200。poptest 不断优化课堂的案例,培养学员实际解决问题的能力。html
当Java程序申请内存,超出VM可分配内纯的时候,VM首先可能会GC,若是GC完仍是不够,或者申请的直接超够VM可能有的,就会抛出内 存溢出异常。从VM规范中咱们能够获得,一下几种异常。java
java.lang.StackOverflowError:(不多)
java.lang.OutOfMemoryError:heap space(比较常见)
java.lang.OutOfMemoryError: PermGen space (常常出现)安全
java.lang.OutOfMemoryError: GC overhead limit exceeded(某项操做使用大量内存时发生)服务器
如下分别解释一下,从最多见的开始:并发
java.lang.OutOfMemoryError: PermGen space 这个异常比较常见,是说JVM里的Perm内 存区的异常溢出,因为JVM在默认的状况下,Perm默认为64M,而不少程序须要大量的Perm区内 存,尤为使用到像Spring等框架的时候,因为须要使用到动态生成类,而这些类不能被GC自动释放,因此致使OutOfMemoryError: PermGen space异常。解决方法很简单,增大JVM的 -XX:MaxPermSize 启动参数,就能够解决这个问题,如过使用的是默认变量一般是64M[5.0 and newer: 64 bit VMs are scaled 30% larger; 1.4 amd64: 96m; 1.3.1 -client: 32m.],改为128M就能够了,-XX:MaxPermSize=128m。若是已是128m(Eclipse已是128m了),就改为 256m。我通常在服务器上为安全起见,改为256m。框架
java.lang.OutOfMemoryError:heap space或其它OutOfMemoryError,这个异常实际上跟上面的异常是一个异常,但解决方法不一样,因此分开来写。上面那个异常是由于JVM的perm区内 存区分少了引发的(JVM的内 存区分为 young,old,perm三种)。而这个异常是由于JVM堆内 存或者说整体分少了。解决方法是更改 -Xms -Xmx 启动参数,一般是扩大1倍。xms是管理启动时最小内 存量的,xmx是管里JVM最大的内 存量的。
注:OutOfMemoryError可能有不少种缘由,根据JVM Specification, 可能有一下几种状况,我先简单列出。stack:stack分区不能动态扩展,或不足以生成新的线程。Heap:须要更多的内 存,而不能得到。Method Area :若是不能知足分配需求。runtime constant pool(从Method Area分配内 存)不足以建立class or interface。native method stacks不可以动态扩展,或生成新的本地线程。工具
java.lang.OutOfMemoryError: GC overhead limit exceeded,这个是JDK6新添的错误类型。这个hotspot VM1.6定义的一个策略,是一种保护机制,经过计算GC时间来预测是否须要OOM了,提早抛出异常,防止OOM的发生,官方的定义是:并行/并发回收器在GC回收时间过长会抛出OutOfMemoryError(过长的定义是超过98%的时间用来GC并回收了不到2%的堆内存,用来避免内存太小形成应用不能正常工做。我在JSP导大Excel的时候碰到过。最终解决方案是,关闭该功能,使用—— -XX:-UseGCOverheadLimit,预测OOM有啥用呢?虽然可能不能最终拯救你的应用,可是能够在挂掉前作最后的挣扎,好比数据保存和保存现场(Heap Dump),固然这个策略会带来好比加载某一个大内存时频繁OOM。加入生产环境遇到这个问题,在不知道缘由的状况下不要简单规避这个问题,能够经过-verbose:gc -XX:+PrintGCDetails看一下究竟是什么缘由形成的异常。一般缘由都是由于年老代(old区)占用过多致使频繁FullGC,最终致使GC overhead limit exceed。若是gc log不够能够借助JProfile等工具查看内存占用,old区是否有内存泄漏。。分析内存泄漏有一个方法 -XX:HeapDumpOnOutOfMemoryError, 这样OOM时会自动作Heap Dump,能够拿MAT来排查了。另外留意新生代(young区),若是有过多短暂对象分配,可能也会致使这个异常。post
最后说说java.lang.StackOverflowError,老实说这个异常我也没遇见过,但JVM Specification就提一下,规范上说有一下几种境况可能抛出这个异常,一个是Stacks里的线程超过容许的时候,另外一个是当native method要求更大的内 存,而超过native method容许的内 存的时候。根据SUN的文档,提升-XX:ThreadStackSize=512的值。性能
总的来讲调优JVM的内 存,组要目的就是在使用内 存尽量小的,使程序运行正常,不抛出内 纯溢出的bug。并且要调好最小内 存,最大内 存的比,避免GC时浪费太多时间,尤为是要尽可能避免FULL GC。测试
补充:因为JDK1.4新增了nio,而nio的buffer分配内存比较特殊(读写流能够共享内存)。若是有大量数据交互,也可能致使java.lang.OutOfMemoryError。相应的JDK新增了一个特殊的参数:-XX:MaxDirectMemorySize 默认是64M,能够改大些如128M。
-XX:MaxDirectMemorySize=<size>Specifies the maximum amount of memory in bytes that the Java™ NIO library can allocate for direct memory buffers. The default is 64 megabytes, which corresponds to-XX:MaxDirectMemorySize=64m . The use of direct memory buffers can minimize the copying cost when doing I/O operations.