#什么是内存溢出
内存溢出是指应用系统中存在无法回收的内存或者使用的内存过多,最终使得程序运行所需要的内存大于JVM所提供的最大内存。
#java如何管理内存
java的内存管理就是对象的分配和释放问题。在java中,内存的分配是由程序来完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的,开发者不需要通过调用GC来释放内存,因为不同的JVM实现者可能使用不同的算法管理GC,有的是内存使用达到一定程度时,GC才开始工作,也有定时执行的,有的是中断式执行GC。
#GC回收机制
GC只能回收无用并且不再被其他对象引用的那些对象所占用的空间。java的内存垃圾回收机制是从程序的主要运行对象开始检查引用链,当遍历一遍后发现没有被引用的孤立对象就作为垃圾回收。
#内存溢出的原因
常见的有以下几种:
①内存中加载的数据量过于庞大,如一次从数据库取出过多数据
②集合类中有对对象的引用,使用完后未清空,使得JVM不能回收
③代码中存在死循环或循环中产生大量重复的对象实体
④使用的第三方软件中存在BUG
⑤启动参数内存设定值过小
#内存溢出的解决方式
①修改JVM启动参数,直接增加内存。<物理方式>
容器为tomcat:修改catalina.bat
在set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%
下面加
JAVA_OPTS='-Xms512m -Xmx1024m'
JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=64M -XX:MaxPermSize=256m"
其中 JAVA_OPTS='-Xms512m -Xmx1024m'
是设置Tomcat使用的内存的大小.
-XX:PermSize=64M -XX:MaxPermSize=256m
指定类空间(用于加载类)的内存大小
②检查错误日志,查看“OutOfMemMemory”错误前是否有其他的异常或者错误。
--java.lang.OutOfMemoryError: ......java heap space....<堆栈溢出>
--java.lang.OutOfMemoryError: GC overhead limit exceeded
JDK6新增错误类型,当GC为释放很小空间占用大量时间时抛出;一般是因为堆太小,导致异常的原因,没有足够的内存。
【解决方案】:
1、查看系统是否有使用大内存的代码或死循环;
2、通过添加JVM配置,来限制使用内存:
< jvm-arg>-XX:-UseGCOverheadLimit< /jvm-arg>
--java.lang.OutOfMemoryError: PermGen space:这种是P区内存不够,可通过调整JVM的配置:
< jvm-arg>-XX:MaxPermSize=128m< /jvm-arg>
< jvm-arg>-XXermSize=128m< /jvm-arg>
【注】:
JVM的Perm区主要用于存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space,这个区域成为年老代,GC在主程序运行期间不会对年老区进行清理,默认是64M大小,当程序需要加载的对象比较多时,超过64M就会报这部分内存溢出了,需要加大内存分配,一般128m足够。
③对代码进行走查和分析,找出可能发生内存溢出的位置。重点排查一下几点:
–检查代码中是否有死循环或递归调用
–检查是否有大循环重复产生新对象实体
–检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。
–检查List、Map等集合对象是否有使用完后,未清除的问题。List、Map等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。
④使用内存查看工具动态查看内存使用情况:Optimizeit Profiler、JProbe Profiler、JinSight和Java1.5的Jconsole等。
一般来说,一个正常的系统在其启动完成后其内存的占用量是基本稳定的,而不应该是无限制的增长的。持续地观察系统运行时使用的内存的大小,可以看到在内存使用监控窗口中是基本规则的锯齿形的图线,如果内存的大小持续地增长,则说明系统存在内存泄漏问题。