我开发了一个持续运行的java程序,这个程序出现内存泄漏,程序在运行期间内存会不断增长直到抛出内存溢出异常。
我这个程序使用了死循环与jni技术。
我想问两个问题:
1、虚拟机会不会回收死循环内的对象(在该线程停止之前),如果不会,如何释放掉这些内存。
2、我知道native方法中的字符串与数组等内存需要手动回收,但是return的不需要,由虚拟机来处理,但我我不知道成员变量是不是需要回收内存,因为成员变量是虚拟机来管理的,但是在native方法中要对他们进行操作,如果要回收会不会导致成员变量值变成空而无法使用,因为native是用来赋值的,java里面要调用这些对象成员变量的值。

解决方案 »

  1.   

    你可以试着一起调下面的两个方法:
    System.gc();
    Runtime.getRuntime().runFinalization();但不建议使用太多!还是检查一下代码吧!
    1 先检查一下静态变量,看其是否会不但增容,而没有释放!
    2 在对数据量较大的集合类如list,map....操作完后是否释放掉了内存空间,建议clear一下.
    3 对流的操作结束后,是否确定关闭!
    4 其他代码逻辑!
      

  2.   

    我调用了GC,但是没用,对于map与list集合没有释放应该不用担心,因为我都是用的局部变量而不是成员变量。
    对流的操作肯定关闭了,因为有大量用户使用,流不关闭会瞬间出现问题。
      

  3.   

    在java里你只要明确把一个对象赋为null之后就会引起gc的兴趣的
    jni就不知道了
      

  4.   

    基本上不用去找虚拟机的问题,你是不是有List,Array或Map 之类的只管加不删除的。
      

  5.   

    你应该从三个方面考虑:
    1、Java方面
    检查代码,查看内存泄漏,这个可以借助一些工具,如OptimizeIT、DevPartner或JProbe、JProfiler都可以看看,尤其要注意一些集合,对于集合来说,要先把集合中对象一层层释放,然后再把集合释放。另外还要注意交叉引用,要把引用关系打断。
    2、JNI方面
    查看C/C++代码是否存在内存泄漏,指针有没有释放等等。另外再创建这类的对象时,不要频繁创建,因为系统资源是很昂贵的。
    3、程序执行逻辑上考虑
    最后要检查程序的执行逻辑,看看是不是做了不该做的事情,多调用了不该调用的函数。
      

  6.   

    使用死循环是件很危险的事情。
    JAVA基本上不能手控进行内存回收
    可能的话 自己重新修改代码结构吧!
      

  7.   

    只能使用死循环,因为要监听读卡设备,如果你有不用死循环监听读卡设备的方法请指教。
    因为用到jni,native方法用C开发的,这部分还是可以手控回收内存的(其实我不想手控回收,但是不得不这么做)。
    如果在没有找到问题的根源之前,你认为重构代码能够解决问题么,如果重构没有解决问题但是有用到那么多人时,那不是浪费力气么?
    其实我大致觉得造成内存泄漏的原因就是虚拟机对未停止线程的内存回收的问题,以及jni调用成员变量的内存问题。至于集合对象中的对象引用是不用担心的,因为我没有把任何集合类设置为成员变量或者静态变量,集合变量都是局部变量。
    不过8楼的那些工具我会拿来用的。
    还是继续等等,看有没有对jni了解比较深入的人或者对java内存回收机制比较了解的人。
      

  8.   

    垃圾回收一直是比较烦的问题,不要迷信Java的自动回收机制,自动回收在有些情况下是根本不回收.
      

  9.   

    在运行大程序的时候,手动调用System.runFinalization()比较重要,一来可以加快速度,而来显示调用回收内存
      

  10.   

    楼主去看下下面的分析吧:
    http://www.enet.com.cn/article/2006/0119/A20060119495081.shtml
      

  11.   

    垃圾回收是一个优先级很低的线程,即使你手工调用也不会起作用。
    把不需要的局部变量赋值为null是一个好的办法。
      

  12.   


    只要内存没被占满,Java就不会启动垃圾回收机制,因为回收机制也需要占有内存。我就知道这个。
      

  13.   

    java的自动回收不是很管用的,内存泄漏还是要找自己代码的问题
      

  14.   

    不用的对象设置为null,over
      

  15.   

        不一定是内存不占满就不回收,而是你不根本无法知道何时回收。和薛定谔的猫有些一样,就是你不去看,根本不知道垃圾回收器运行了没有。但是就我所知,应该没办法看gc是否运作。
         至于楼主,如果真的对内存消耗很在意的话,还是不要用java了。因为在java这一端,你是没法处理内存的。就算你调用一百次gc。实际上可能一次垃圾收集都没做。因为gc在java中,你没办法调用它,只能告诉jvm可以运行它了。
      

  16.   

    问题是项目已经用java实现了,而且公司主要是java为主,其它语言的技术支持力量不够,而且本人也只是java专长,其他语言可以说是一窍不通,所以不考虑使用其它语言实现。
      

  17.   

         那我有个思路,不知道可不可行?
          就是如果内村不够的时候,把所有其他线程停了。然后调用gc。
           有些异想天开。不过你可以看看最近几个java写的服务器程序的代码。因为估计他们也会有你相同的问题。