请帮忙分析一下这可能是什么原因一起的我们现在只能每过一周都重启一下

解决方案 »

  1.   

    用Jprobe或JPrifile进行内存跟踪,看看内存泄露问题
    或者用jdk自带工具进行分析------------------------------------------------------------
    JDK5的jconsole(+调试内存泄漏经验介绍 jps/jmap/jstat)
    2008-12-18 10:56
    http://marshal.javaeye.com/blog/138879 jconsole工具介绍
    Jconsole(Java Monitoring and Management Console)是从java5开始,在JDK中提供的java监控和管理控制台。用于对JVM中内存,线程和类等的监控。
    基本配置
    -本文使用java6,SUN JDK1.6.0_03,使用JDK1.5版本使用略有不同。
    -本文使用windows XP。
    -确认jdk的bin目录设置到环境变量Path中。
    -在命令行中输入:【jconsole】。如果弹出窗口,说明配置可用。
    基本使用
    这里使用的是本地JVM监控,如果要监控远程的JVM需要另外的配置。
    首先,启动需要监控的Java应用程序。
    通过任务管理器的进程标签,查看该进程的PID,比如是1388
    在命令行启动jconsole:【jconsole 1388】
    在启动的界面中:
    -概述:有关堆内存使用情况,线程,类加载和CPU使用情况的综述;
    -内存:内存的详细情况,堆和其他内存;
    -线程:峰值/活动线程,另外,各个线程的明细信息,检测死锁;
    -类:监控加载和卸载的类;
    -vm摘要:有关vm的明细信息
    -MBean:当前Java程序的MBean(如果有的话)的操作。
    http://gq913.javaeye.com/blog/160979 tomcat中配置jconsole远程访问(附命令)
    catalina.bat:
    set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port="9004" -Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false"
    catalina.sh:
    JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9004 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
    一些命令:
    访问本地:
    【注意:如果启动的jconsole和JVM(Java)不是在同一个JDK目录下使用下面命令:jconsole pid】
    http://xsen.javaeye.com/blog/150317 配置jconsole远程监视 (jconsole Remote Monitoring)
    环境:
    服务器端: Linux + jdk1.5.0 + resin3 /客户端: Windows + jdk1.5.0
    jconsole远程监视的配置步骤如下:
    服务器端:
    1. mkdir $JAVA_HOME/jconsole_pwd
    2. cp $JAVA_HOME/jre/lib/management/jmxremote.password.template $JAVA_HOME/jconsole/jmxremote.password -> chmod 600 $JAVA_HOME/jconsole/jmxremote.password
    3. vi jmxremote.password 去掉#monitorRole RED前的注释并将RED修改为你要设置的密码。(安全起见,只开放有只读权限的用户)
    4. 修改 $RESIN_HOME/bin/wrapper.pl,为$JAVA_ARGS添加三个参数:
    -Dcom.sun.management.jmxremote.port=1010
    -Dcom.sun.management.jmxremote.password.file=/usr/local/jdk1.5.0/jconsole_pwd/jmxremote.password
    -Dcom.sun.management.jmxremote.ssl=false
    5. 执行hostname -i ,如果显示的是127.0.0.1,则需要修改/etc/hosts文件
    6. vi /etc/hosts,修改如下:
    #127.0.0.1              localhost localhost.localdomain localhost
    服务器的真实IP地址        localhost localhost.localdomain localhost
    具体原因是服务器端解释机器名的问题,相关问题见: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6209663
    服务器端配置参见: http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html#remote
    7. 启动resi -> netstat -na|grep 1010 查看1010端口是否已在监听
    客户端:
    1. 打开cmd窗口,输入jconsole
    2. 指定连接参数:
    远程主机: 服务器的真实IP地址
    端口: 1010 ($JAVA_ARGS中-Dcom.sun.management.jmxremote.port指定的端口)
    用户名: monitorRole (jmxremote.password中指定的用户名)
    密码: your_password(jmxremote.password中设置的密码)
    3. 连接 -> OK
    客户端配置参见: http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html
    jconsole文档地址:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jconsole.html
    http://fly-hyp.javaeye.com/blog/300024 java调试内存泄漏经验介绍
    修订记录:创建:2008年12月23日,修改:2008年12月24日 增加调试流程描述
    今天要处理项目下的一个内存泄露的问题。使用了jprobe 工具,在测试环境反复调试不能发现问题的原因。最后使用jdk自带的jps jmap jstat 等工具顺利的查找到了内存泄露的原因。下面对jdk自带的jps jmap jstat工具总结介绍一下,希望以后同道中人google一下,找到这篇文章对大家有所帮助。尽量介绍的简明扼要,如果需要最详细的参考请翻阅jdk doc tools部分,如果有什么疑问请留言。
    jps:
        相当于linux下的ps,列出所有java相关线程的pid等信息
        example:
           [tdwiki@installed-host-eth0 ~]$ jps   
           18861 Bootstrap
           1418 Jps
    jmap:
        显示java进程内存使用的相关信息
       jmap pid                   打印内存使用的摘要信息
       jmap -histo pid >mem.txt         打印比较简单的各个有多少个对象占了多少内存的信息,一般重定向的文件
    jmap -dump:format=b,file= mem.dat pid        将内存使用的详细情况输出到mem.dat 文件
            用jhat命令可以参看 jhat -port 7000 mem.dat
            在浏览器中访问:http://10.5.22.65:7000/ 查看详细信息
    jstat:
        显示java虚拟机的一些统计信息
       jstat -选项 pid 间隔显示时间 显示次数
         jstat -gc 18861 250 10
       jstat -gccapacity 18861 250 10
       jstat -gcnew 18861 250 10
       jstat -gcnewcapacity 18861 250 10
       jstat -gcold 18861 250 10
    我的调试流程
    内存泄漏一般都是有一定特征的,任何代码和数据都要占用内存,我简单总结内存泄漏的特征是内存占用不可控制,GC不可回收。我追踪内存使用量的曲线发现一些特征,在估计虚拟机即将崩溃时,使用 jmap -histo pid >mem.txt 发现相关内存泄漏的对象占用非常打比例的内存空间,然后很容易猜测问题大概的位置,一下子就解决了。
      

  2.   

    如果是因为数据量太大,而引起的频繁Gc,可以设置一下GC的机制---------------------------------------------------------------------
    1. 常见配置汇总
    1. 堆设置
    * -Xms:初始堆大小
    * -Xmx:最大堆大小
    * -XX:NewSize=n:设置年轻代大小
    * -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
    * -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
    * -XX:MaxPermSize=n:设置持久代大小 2. 收集器设置
    * -XX:+UseSerialGC:设置串行收集器
    * -XX:+UseParallelGC:设置并行收集器
    * -XX:+UseParalledlOldGC:设置并行年老代收集器
    * -XX:+UseConcMarkSweepGC:设置并发收集器 3. 垃圾回收统计信息
    * -XX:+PrintGC
    * -XX:+PrintGCDetails
    * -XX:+PrintGCTimeStamps
    * -Xloggc:filename 4. 并行收集器设置
    * -XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
    * -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
    * -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n) 5. 并发收集器设置
    * -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
    * -XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
    四、调优总结 1. 年轻代大小选择
    * 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
    * 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。 2. 年老代大小选择
    * 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得:

    * 并发垃圾收集信息
    * 持久代并发收集次数
    * 传统GC信息
    * 花在年轻代和年老代回收上的时间比例
    减少年轻代和年老代花费的时间,一般会提高应用的效率
    * 吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。 3. 较小堆引起的碎片问题
    因 为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间 较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出 现“碎片”,可能需要进行如下配置:
    * -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
    * -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩