什么是内存溢出outofmemory?怎么解决
本⽂主要内容来源于⽹络,博主⾃⼰整理⽽成,仅做知识分享,如有侵权请联系,会及时删除。
1.什么是内存溢出?
内存溢出是指应⽤系统中存在⽆法回收的内存或使⽤的内存过多,最终使得程序运⾏要⽤到的内存⼤于虚拟机能提供的最⼤内存。为了解决Java中内存溢出问题,我们⾸先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中,内存的分配是由程序完成的,⽽内存的释放是由垃圾收集器(GarbageCollection,GC)完成的,程序员不需要通过调⽤GC函数来释放内存,因为不同的JVM实现者可能使⽤不同的算法管理GC,有的是内存使⽤到达⼀定程度时,GC 才开始⼯作,也有定时执⾏的,有的是中断式执⾏GC。但GC只能回收⽆⽤并且不再被其它对象引⽤的那些对象所占⽤的空间。Java的内存垃圾回收机制是从程序的主要运⾏对象开始检查引⽤链,当遍历⼀遍后发现没有被引⽤的孤⽴对象就作为垃圾回收。
2.为什么会出现内存溢出?
常见有以下情况:
(1)内存中加载的数据量过于庞⼤,如⼀次从数据库取出过多数据;
(2)集合类中有对对象的引⽤,使⽤完后未清空,使得JVM不能回收;
(3)代码中存在死循环或循环产⽣过多重复的对象实体;
(4)使⽤的第三⽅软件中的BUG;
(5)启动参数内存值设定的过⼩
3.内存溢出解决⽅法
内存溢出虽然很棘⼿,但也有相应的解决办法,可以按照从易到难,⼀步步的解决。
怎么申请博客第⼀步,就是修改JVM启动参数,直接增加内存。这⼀点看上去似乎很简单,但很容易被忽略。JVM默认可以使⽤的内存为64M,Tomcat默认可以使⽤的内存为128MB,对于稍复杂⼀点的系统就会不够⽤。在某项⽬中,就因为启动参数使⽤的默认值,经常报“OutOfMemory”错误。因此,-Xms,-Xmx参数⼀定不要忘记加。
第⼆步,检查错误⽇志,查看“OutOfMemory”错误前是否有其它异常或错误。在⼀个项⽬中,使⽤两个数据库连接,其中专⽤于的数据库连接使⽤DBCP连接池管理,⽤户为不将短信发出,有意将数据库连接⽤户名改错,使得⽇志中有许多数据库连接异常的⽇志,⼀段时间后,就出现“OutOfMemor
y”错误。经分析,这是由于DBCP 连接池BUG引起的,数据库连接不上后,没有将连接释放,最终使得DBCP报“OutOfMemory”错误。经过修改正确数据库连接参数后,就没有再出现内存溢出的错误。
查看⽇志对于分析内存溢出是⾮常重要的,通过仔细查看⽇志,分析内存溢出前做过哪些操作,可以⼤致定位有问题的模块。
第三步,安排有经验的编程⼈员对代码进⾏⾛查和分析,出可能发⽣内存溢出的位置。重点排查以下⼏点:
1 检查代码中是否有死循环或递归调⽤。
2检查是否有⼤循环重复产⽣新对象实体。
3检查对数据库查询中,是否有⼀次获得全部数据的查询。⼀般来说,如果⼀次取⼗万条记录到内存,就可能引起内存溢出。这个问题⽐较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,⼀次查询就有可能引起内存溢出。因此对于数据库查询尽量采⽤分页的⽅式查询。
检查List、MAP等集合对象是否有使⽤完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引⽤,使得这些对象不能被GC回收。
第四步,使⽤内存查看⼯具动态查看内存使⽤情况。某个项⽬上线后,每次系统启动两天后,就会出现内存溢出的错误。这种情况⼀般是代码中出现了缓慢的内存泄漏,⽤上⾯三个步骤解决不了,这就需要使⽤内存查看⼯具了。
内存查看⼯具有许多,⽐较有名的有:Optimizeit Profiler、JProbeProfiler、JinSight和Java1.5的Jconsole等。它们的基本⼯作原理⼤同⼩异,都是监测Java程序运⾏时所有对象的申请、释放等动作,将内存管理的所有信息进⾏统计、分析、可视化。开发⼈员可以根据这些信息判断程序是否有内存泄漏问题。⼀般来说,⼀个正常的系统在其启动完成后其内存的占⽤量是基本稳定的,⽽不应该是⽆限制的增长的。持续地观察系统运⾏时使⽤的内存的⼤⼩,可以看到在内存使⽤监控窗⼝中是基本规则的锯齿形的图线,如果内存的⼤⼩持续地增长,则说明系统存在内存泄漏问题。通过间隔⼀段时间取⼀次内存快照,然后对内存快照中对象的使⽤与引⽤等信息进⾏⽐对与分析,可以出是哪个类的对象在泄漏。
通过以上四个步骤的分析与处理,基本能处理内存溢出的问题。当然,在这些过程中也需要相当的经验与敏感度,需要在实际的开发与调试过程中不断积累。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论