JAVA中的内存泄漏
Java中的内存泄露,就是:不再会被使用的对象的内存不能被回收,就是内存泄露。也可以说一个不再被程序使用的对象或变量一直被占据在内存中。
Java中的内存管理
Java中的内存管理是垃圾收集器(GC)的责任。
在应用程序运行时,应用程序会创建大量对象,每个对象都有它的生命周期。在内存中,其他对象引用的对象称为活动对象。任何活动对象不再引用的对象都被视为死对象,称为垃圾。查找和释放(也称为回收)这些对象使用的空间的过程称为垃圾收集。
垃圾收集解决了许多(但不是全部)内存分配问题。例如,我们可以无限期地创建对象并继续引用它们,直到没有更多可用内存(内存不足错误)。垃圾收集是一项复杂的任务,需要时间和资源。它在空间上运行,该空间通常从称为堆的大型内存池中分配。
什么情况下会出现内存泄漏
但是在Java中,我们不用(也没办法)自己释放内存,无用的对象由GC自动清理,这也极大的简化了我们的编程工作。但,实际有时候一些不再会被使用的对象,在GC看来不能被释放,就会造成内存泄露。
我们知道,对象都是有生命周期的,有的长,有的短,如果长生命周期的对象持有短生命周期的引用,就很可能会出现内存泄露。我们举一个简单的例子:
public class Simple {
Object object;
public void method1(){
object = new Object();
//...其他代码
}
}
这里的object实例,其实我们期望它只作用于method1()方法中,且其他地方不会再用到它,但是,当method1()方法执行完成 后,object对象所分配的内存不会马上被认为是可以被释放的对象,只有在Simple类创建的对象被释放后才会被释放,严格的说,这就是一种内存泄 露。
解决方法就是将object作为method1()方法中的局部变量。当然,如果一定要这么写,可以改为这样:
public class Simple {
Object object;
public void method1(){
object = new Object();
//...其他代码
object = null;
}
}
这样,之前“new Object()”分配的内存,就可以被GC回收。
集合中的内存泄漏,比如 HashMap、ArrayList 等,这些对象经常会发生内存泄露。比如当它们被声明为静态对象时,它们的生命周期会跟应用程序的生命周期一样长,很容易造成内存不足。
下面给出了一个关于集合内存泄露的例子。
Vector v=new Vector(10);
for (int i=1;i<100; i++)
{
Object o=new Object();
v.add(o);
o=null;
}
//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。
在这个例子中,我们循环申请 Object 对象,并将所申请的对象放入一个 Vector 中,如果我们仅仅释放引用本身,那么 Vector 仍然引用该对象,所以这个对象对 GC 来说是不可回收的。
因此,如果对象加入到 Vector 后,还必须从 Vector 中删除,最简单的方法就是将 Vector 对象设置为 null。
如何提高Java中的内存利用率
- 不要分配过多的内存。仅在需要时分配内存。这特别适用于Java数组。
- 不要坚持参考。一旦使用了对象并且不再需要该对象,请为其指定null引用。
- 不要依赖System.gc()来运行垃圾收集。
如何防止内存泄漏的发生?
- 在确认一个对象无用后,将其所有引用显式的置为null。
- 专业检查 Java 内存泄漏的工具:Plumbr 、Eclipse Memory Analyzer、JProbe Profiler、JVisualVM 等。
总的来说,内存泄露问题,还是编码不认真导致的,我们并不能责怪JVM没有更合理的清理。
https://howtodoinjava.com/java/garbage-collection/revisiting-memory-management-and-garbage-collection-mechanisms-in-java/
http://www.ityouknow.com/java/2019/05/23/memory-leak.html
https://www.cnblogs.com/1130136248wlxk/articles/6394889.html
https://www.jianshu.com/p/54b5da7c6816