关于java.lang.outofmemoryerror的报错处理

来源:互联网 发布:mac解压zip文件 编辑:程序博客网 时间:2024/04/29 20:59
问题陈述:
   tomcat服务器运行一段时间后,tomcat控制台报错:
   java.lang.outOfMemoryError,java.lang.outOfMemoryError
   然后tomcat服务立即死,只有重启tomcat才能恢复服务

初步确定原因
  1,java虚拟机jvm内存过小
  2,程序不严密,产生太多的垃圾

解决对策:
  
针对原因1
    增加jvm的内存大小。
    JVM即是java虚拟机,它运行时候占用一定的内存,其大小是有限定的,如果程序在运行时jvm占用的内存大于某个限度,则会产生内存益处,也就是“java.lang.outofmemoryerror”。
    作为web容器的tomcat(包括resin等)在运行时候,会直接或间接产生一个java.exe进程,可以看成一个jvm进程。由于这些web容器在不停的运行,也就是jvm不停的工作,jvm会不断的产生垃圾(所胃的垃圾,简单可认为是指程序进行后遗留下的无用的对象),也会不停的回收垃圾。当回收垃圾的速度比产生垃圾的速度的慢时,垃圾就会不停的增长,当垃圾增长超过一定限度,也就是垃圾对象占用的内存超过jvm内存的最大限度。此时jvm就会出现运行时错误,也就是error,由于error属于致命错误,不能处理,故tomcat等就会断掉,只有重启tomcat。
    针对此,我们可以设想,如果jvm内存的没有限度,并且有无限大的内存,那jvm就永远不会出现内存溢出了。但是,傻子都知道我们在做白日梦。既然这样行不通,那我们就退一步,所胃退一步海阔天空嘛,我们可以适当增大jvm的最大内存,以缓解jvm来不及回收垃圾而导致的内存不断增长。jdk1.4默认jvm的最大内存为128M,我们可以把tomcat等web容器的jvm最大内存加大,比如我们可以增大到256M,甚至1G等,只要不超过计算的内存都行,不过凡事都有个度,设置过大肯定不是最好的。至于要个jvm设置多大的内存则要通过我们不断尝试。
    如何增加jvm的内存呢?
    第一,在执行某个class文件时候,可以使用java -Xmx256M aa.class来设置运行aa.class时jvm所允许占用的最大内存为256M。
    第二,对tomcat容器,可以在启动时对jvm设置内存限度。对tomcat,可以在catalina.bat中添加:
    "set CATALINA_OPTS=-Xms128M -Xmx256M
    set JAVA_OPTS=-Xms128M -Xmx256M",或者把%CATALINA_OPTS%和%JAVA_OPTS%代替为-Xms128M -Xmx256M,其具体操作可以到网上去找找。
    第三,对resin容器,同样可以在启动时对jvm设置内存限度。在bin文件夹下创建一个startup.bat文件,内容如下:
@echo off
call "httpd.exe"  "-Xms128M" "-Xmx256M"
:end
其中"-Xms128M"为最小内存,"-Xmx256M"为最大内存。
   第四,其他容器,如ibm webswhere,可以通过配置文件加大jvm内存。
   第五,修改jdk内核,个人想法,但没去研究过。
 
  针对原因2:
    由于jvm产生的垃圾是由我们所写的代码产生的,质量好的代码产生的垃圾少,相反就会产生很多垃圾。由于jvm的最大内存不能无限增大,故增大jvm的最大内存应该是在代码已经达到很优化时才实施的,所以优化程序才是我们最先要做的。
    如何优化程序:
    第一,避免死循环。仔细检查程序,防止出现死循环,这是比较容易检查的。
    第二,可以适当手动回收垃圾。
    第三,应该及时释放种资源:内存, 数据库的各种连接。 
    释放资源的时候不能依赖于java的垃圾自动回收机制,最好也不要用finalize方法,因为无用单元回收不是一个完全可以确定的过程,作为低优先级进程,往往是系统没有内存时才调用垃圾回收进程。
由于我们在Java程序中声明了好多对象,占用了内存空间,程序结束时没有将这些对象或对象的引用进行释放,从而导致Java虚拟机(JVM)进行垃圾回收(GC)时,不能够回收这些对象。这样,Java所用的内存就会一直增加,直至溢出,进而导致Resin死机。 
导致Java内存溢出的根本原因是Java程序的不规范或不健壮。因此,从根本上解决Java内存溢出的唯一方法就是修改Java程序,及时地释放没用的对象,释放内存空间。 
    除了这个方法以外,还有一些应急措施,可以临时缓解一下系统的运行。Resin默认情况是死机以后不能访问网站,必须手动重启Resin,但不可能一直看在机器旁边,看Resin有没有死机。所以这里介绍一种让Resin自重启的方法。 
打开Resin的配置文件resin.conf(一般情况下,该文件在Resin目录的conf文件夹下)。里面有一段内容如下所示: 

    这段内容默认情况下是被注释的。它的功能是让Resin每隔一分钟就测试一下能否访问/ping/ping.jsp文件,测试时间是1s,如果不成功,就重试三次。如果三次都不成功,Resin就自动重启。所以将这段话下半部分(从"")的注释去掉,然后在Resin的发布目录中新建一个文件夹ping,在ping文件夹下新建一个ping.jsp文件,文件中可以写入简单的一句话,如:。 
好,大功告成,启动Resin,这样就不用担心Java内存溢出导致Resin死机了,因为Resin死机后会马上重新启动。 
    当然,这只是应急措施,不是长久之计。如果从长计议,还是要耐心的更改Java程序!
0 0