文章目录
引起java内存泄露的几种场景
OOM 全称 Out Of Memory 来源于
java.lang.OutOfMemory
,当java因为内有足够的内存来为对象分配空间并且垃圾回收器也没有空间可回收时,就会抛出这个error,并非exception,因为这个问题已经严重到不足以被应用处理
1. 静态集合类
如HashMap
,LinkedList
等,如果这些容器是京台的,那么它们的生命周期与程序一致,则容器中的对象在程序结束前将不能被释放,从而造成内存泄漏.简单而言,长生命周期的对象持有短生命周期的对象的引用,尽管段生命周期的对爱不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收
2.各种连接,如数据库,网络连接和IO等
在对数据库进行操作的过程中,需要首先建立数据库的连接,当不再使用时,需要调用close方法来释放与数据库的连接,只有连接被关闭后,垃圾回收期才会回收对应的对象,否则,将会造成大量的对象无法被回收,从而引起内存泄露
3.变量不合理的作用域
一般而言,一个变量的定义的作用范围大于其使用范围,很有可能造成内存泄漏,另一方面,如果没有及时把对象时设置为null
,也有可能造成内存泄露的方法
public class UsingRandom {
private String msg;
public void receiveMsg(){
readFromNet();// 从网络中接受数据保存到msg中
saveDB();// 把msg保存到数据库中
}
}
如上述伪代码所示,通过readFromNet方法接受消息保存到变量msg中,然后调用savedb方法存到数据库里面,这时候msg就没用了,由于msg的生命周期与对象的生命周期相同,此时msg不会被回收.会有内存泄露的风险.
实际上这个msg变量放在readFromNet()
内部,放方法使用完,那么msg的生命周期与方法相同,.此时方法结束后msg就会被回收了,还有一个方法就是方法内把msg设置为null,这时msg的变量因为没有引用,也会被回收.
4.内部类持有外部类
如果一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类就被长期引用了…即使那个外部类实例对象不在使用,也不会被垃圾回收,
5,改变hash值
当一个对象被存储进hashset集合时,就不能修改这个对象的哪些参与计算hash计算的字段了,否则对象修改后的hash值与最初存储进hashset集合时的hash值就不一样了,这个时候,就是在contains
方法使用该对象的当前引用最为参数去set中检索对象,也将返回找不到对象的结果,这将会导致无法从hashset集合中单独删除当前对象
6.栈的pop方法弹出的对象不会被当做垃圾回收
即使时程序不在使用栈中的这些对象,他们也不会被回收,因为栈中仍然保存着这些对象的引用,俗称过期引用,解决方法就是,一旦引用过期,清空这些引用,将引用置空.
7.监听器
增加各种监听器最后在释放的时候没有删除这些监听器,从而增加的内存泄露的风险
8.单例模式
单例的静态特性使得其生命周期跟应用的生命周期一样长,所以如果使用不恰当的话,很容易造成内存泄漏