我开发了一个持续运行的java程序,这个程序出现内存泄漏,程序在运行期间内存会不断增长直到抛出内存溢出异常。
我这个程序使用了死循环与jni技术。
我想问两个问题:
1、虚拟机会不会回收死循环内的对象(在该线程停止之前),如果不会,如何释放掉这些内存。
2、我知道native方法中的字符串与数组等内存需要手动回收,但是return的不需要,由虚拟机来处理,但我我不知道成员变量是不是需要回收内存,因为成员变量是虚拟机来管理的,但是在native方法中要对他们进行操作,如果要回收会不会导致成员变量值变成空而无法使用,因为native是用来赋值的,java里面要调用这些对象成员变量的值。
我这个程序使用了死循环与jni技术。
我想问两个问题:
1、虚拟机会不会回收死循环内的对象(在该线程停止之前),如果不会,如何释放掉这些内存。
2、我知道native方法中的字符串与数组等内存需要手动回收,但是return的不需要,由虚拟机来处理,但我我不知道成员变量是不是需要回收内存,因为成员变量是虚拟机来管理的,但是在native方法中要对他们进行操作,如果要回收会不会导致成员变量值变成空而无法使用,因为native是用来赋值的,java里面要调用这些对象成员变量的值。
System.gc();
Runtime.getRuntime().runFinalization();但不建议使用太多!还是检查一下代码吧!
1 先检查一下静态变量,看其是否会不但增容,而没有释放!
2 在对数据量较大的集合类如list,map....操作完后是否释放掉了内存空间,建议clear一下.
3 对流的操作结束后,是否确定关闭!
4 其他代码逻辑!
对流的操作肯定关闭了,因为有大量用户使用,流不关闭会瞬间出现问题。
jni就不知道了
1、Java方面
检查代码,查看内存泄漏,这个可以借助一些工具,如OptimizeIT、DevPartner或JProbe、JProfiler都可以看看,尤其要注意一些集合,对于集合来说,要先把集合中对象一层层释放,然后再把集合释放。另外还要注意交叉引用,要把引用关系打断。
2、JNI方面
查看C/C++代码是否存在内存泄漏,指针有没有释放等等。另外再创建这类的对象时,不要频繁创建,因为系统资源是很昂贵的。
3、程序执行逻辑上考虑
最后要检查程序的执行逻辑,看看是不是做了不该做的事情,多调用了不该调用的函数。
JAVA基本上不能手控进行内存回收
可能的话 自己重新修改代码结构吧!
因为用到jni,native方法用C开发的,这部分还是可以手控回收内存的(其实我不想手控回收,但是不得不这么做)。
如果在没有找到问题的根源之前,你认为重构代码能够解决问题么,如果重构没有解决问题但是有用到那么多人时,那不是浪费力气么?
其实我大致觉得造成内存泄漏的原因就是虚拟机对未停止线程的内存回收的问题,以及jni调用成员变量的内存问题。至于集合对象中的对象引用是不用担心的,因为我没有把任何集合类设置为成员变量或者静态变量,集合变量都是局部变量。
不过8楼的那些工具我会拿来用的。
还是继续等等,看有没有对jni了解比较深入的人或者对java内存回收机制比较了解的人。
http://www.enet.com.cn/article/2006/0119/A20060119495081.shtml
把不需要的局部变量赋值为null是一个好的办法。
只要内存没被占满,Java就不会启动垃圾回收机制,因为回收机制也需要占有内存。我就知道这个。
至于楼主,如果真的对内存消耗很在意的话,还是不要用java了。因为在java这一端,你是没法处理内存的。就算你调用一百次gc。实际上可能一次垃圾收集都没做。因为gc在java中,你没办法调用它,只能告诉jvm可以运行它了。
就是如果内村不够的时候,把所有其他线程停了。然后调用gc。
有些异想天开。不过你可以看看最近几个java写的服务器程序的代码。因为估计他们也会有你相同的问题。