在Spring + hibernate 的web应用程序中,我连续做几次批量的操作,在jdk1.6自带的jconsole控制台中监控到内存一直在增加,而未被回收,一开始以为是没有到回收的时间,可过了一个晚上的时间,内存始终在150M左右,没有被回收的迹象,一晚上hibernate Session已经失效,session中的对象应该都被释放了。。最初我jvm的虚拟内存设为 300M,我把jvm的虚拟内存设成250M(200Mtomcat就启动不起来了)也内存也未被回收。如果每天做批量错做,内存肯定会泄露。这问题该怎么解决呢???我在每次执行完saveOrUpdate后执行session.flush(),session.clear();连续执行批量操作内存使用虽然没有一直增加,在上下波动的状态,但也没有被回收。我手动的执行System.gc(),内存即会下降。到底是什么原因会导致内存没有被垃圾回收器回收呢??

解决方案 »

  1.   

    这个不懂。但我在操作Spring+hibernate的时候的经验是重启下服务器,所有的session都被清空!
      

  2.   

    测试的时候可以重启,已经上生产了就不能重启了啊,存在内存泄露问题,哪里有下载 检测内存泄露工具 Optimizeit Profiler 6.0 的地址呢,找了一晚上,网上给的下载地址都访问不了了
      

  3.   

    这样的问题确实很头痛,说明内存未及时回收,
    如果偶尔调查用 System.gc()可以解决,那也是可以的
    因为java 回收内存确实不是实时的
      

  4.   

    如果手动GC可以回收的话,说明被GC的这些对象已经没有引用指向它,可以被回收了,到一定时间就会被回收,但是我等了一晚上都没有被回收掉,而且如果我继续做批量操作的话,内存就会溢出,头疼的问题啊
      

  5.   

    因为你的内存占用的量不到需要回收的点。你可以看看jdk文档中关于gc算法的介绍。根据记忆,内存在jvm中分成两部分,一部分给newer的对象,一部分给older对象.newer的那个部分空间被叫做伊甸园。刚出生的对象都在伊甸园中。伊甸园被分成3个部分,每次gc检查都会把不能释放的对象放置到另外一部分。如果一个对象被反复移动了32次,也叫做32岁,就把它放到older的部分。无论是newer的伊甸园,还是older的部分,内存占用都要到一定的比例,才能触发回收。jconsole中可以分别看到两部分。我怀疑你看到的是Older的空间。因为根据hibernate和spring的特性,有很多长时间缓存的对象,他们应该都在older中。而这部分一直很稳定,没有增长,所以没有gc.jvm有一些参数可以调整各部分内存的大小,你可以查jdk的文档,调小那部分内存看看。祝你好运。
      

  6.   

    我们的项目现在也存在同样的问题关注ING...
      

  7.   

    在开发我的Java应用服务器时,也遇到过内存溢出的问题,同样是基于JMX进行系统监控,并且也使通过Jconsole提供的图形界面发现内存溢出现象;最后用Jprofile解决。
    但是我的问题比楼主的简单,我的问题就是有一个类不停被实例化,并存放至缓存而导致JVM无法回收对象,从而导致内存溢出。
    但楼主的就有点怪异了,显然是内存溢出,但“我手动的执行System.gc(),内存即会下降。”,这说明这些对象在强制执行垃圾回收时,引用被释放了,因此导致对象可以回收吧。但问题的解决还得靠Jprofile了。
    关注一下奇怪之现象
      

  8.   

    用内存检测工具做检测没看出什么原因,最后把程序里不需要的好多list,map去掉就好了
      

  9.   

    估计是tomcat配置的问题?我也遇到了这个问题,在解决ing。