问题描述:
我们的程序是建立在JBOSS应用服务器上的,服务端的堆内存最大为1GB。在服务端启动后,观察服务端JAVA进程占用了300多MB物理内存,然后执行一个批量导入程序,从excel文件中导入65000条数据到数据库中,服务端物理内存占用升到600多MB左右。后面频繁导入相同数量的数据多次,物理内存(包含了堆内存在内,是java进程一共占用的)一直维持在600-800多MB。后面不做任何操作经过10个小时左右,物理内存一直都在600MB左右。GC并没有释放掉不用堆内存,所以怀疑内存泄漏。但是我将服务端的堆内存改为最大350MB,然后启动服务端,并且执行如上导入操作多次,观察堆内存一直维持在340MB左右。例如某次导入完成后堆内存已经340MB了,后面在导入65000条数据,堆内存还是在340MB左右,整个服务端java进程也就450MB左右,只不过GC被频繁调用回收内存。感觉又不像是发生内存泄漏,否则泄漏的内存会不断增加而导致OutOfMemory。结合上述情况,请问各位高手看看是否导入操作发生了内存泄漏???为什么第一次导入操作会使得JAVA进程占用很多物理内存,看了代码不可能申请那么多内存的啊,后面也不释放?

解决方案 »

  1.   

    向楼主共享自己的实际经验致敬
    我也在客户端遇上了这类问题
    java和Excel(大小400K左右)交互复制粘贴的时候,每次内存涨2M,复制几回后内存就溢出了
    但是通过jxl导入不会溢出
    对于Java内存自动回收,用单个文件测试,确实到系统退出就全释放了
    但是在实际项目中测试,测试环境IE+Swing,最多也只能释放75%多点
    导致系统运行越来越慢
    在网上苦寻良方,都是照着教科书乱说的
      

  2.   

    也有可能是office的问题.你开几个excel,过很久再关掉,有时侯就会发现机器性能下降,内存不够用了.
      

  3.   

    不是Office的问题
    我通过txt复制也是一样的
    逐行代码调试发现是Java操作系统粘贴板发生内存狂涨
    但是如果数据量较少的时候没有这种情况
      

  4.   

    JAVA的内存回收有一个原则是尽量在内存已经用完的情况下才开始回收。还有楼主程序如果一次性把65000条记录读到一个集合变量里面的话,只要这个集合的引用的生命周期还没有结束,这65000条记录所占用的内存也不会被回收。建议楼主读一部分,处理一部分。可以避免内存溢出。因为难保有人拿你的程序去读一个几十万条记录的文件。
      

  5.   

    对于这一点,我能说的是JVM占很多的内存,这一些不假,为什么呢,我认为是因为他把一些class与机器码在编辑时,浪费了一些,之后,对于缓存的内容,也需要空间而导致的,还有就是对于代码的编辑工作,要学会对资源的释放!
      

  6.   

    我认为,class占用的内存是无法释放的.另外,jboss支持JMX的.你可以用jboss的JMX接口观察java heap到利用率.taskman看见的是jvm的占用. 比如你jvm用1g,但是里面也许有900M heap是free的. jvm是不会释放这些内存的吧.我还没发现什么时候jvm会主动释放host机的内存
      

  7.   

    各种WEB服务器选择的GC策略不一样,一般只有当可用堆内存少于一定的阈值时,才启动GC,根据你描述的实际情况,估计是JBOSS设定的启动垃圾收集的阈值大于60%
      

  8.   

    遇到过这类问题,导入到30000多的时候就溢出,后来发现是程序问题,因为后台涉及到数据库操作,占用资源多而且不会释放,导致内存一直往上飙。
    解决办法是写个线程,让数据库操作在后台处理,并且定期sleep,就好了
    不知道你这个有没涉及到数据库~~~~