Java中什么时候会出现内存泄漏问题,如何解决内存泄漏问题?
https://blog.csdn.net/weter_drop/article/details/89387564
1.介绍
内存泄露是指不再使用的对象由于仍然被其他对象引用,导致垃圾收集器(GC)不能及时释放这些对象占用的内存从而造成内存空间浪费的现象。
2.常见场景
2.1 未正确释放资源
数据库、网络、输入输出流,这些资源没有显示的关闭。
垃圾回收只负责内存回收,如果对象正在使用资源的话,Java虚拟机不能判断这些对象是不是正在进行操作,比如输入输出,也就不能回收这些对象占用的内存,所以在资源使用完后要调用close()方法关闭。
2.2 单例模式
单例模式只允许应用程序存在一个实例对象,并且这个实例对象的生命周期和应用程序的生命周期一样长,如果单例对象中拥有另一个对象的引用的话,这个被引用的对象就不能被及时回收。解决办法是单例对象中持有的其他对象使用弱引用,弱引用对象在GC线程工作时,其占用的内存会被回收掉,如下示例:
public class SingleTon1 {
private static final SingleTon1 mInstance = null;
private WeakReference<Context> mContext;
private SingleTon1(WeakReference<Context> context) {
mContext = context;
}
public static SingleTon1 getInstance(WeakReference<Context> context) {
if (mInstance == null) {
synchronized (SingleTon1.class) {
if (mInstance == null) {
mInstance = new SingleTon1(context);
}
}
}
return mInstance;
}
}
public class MyActivity extents Activity {
public void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SingleTon1 singleTon1 = SingleTon1.getInstance(new WeakReference<Context>(this));
}
}
2.3 慎用静态成员变量
例如:静态的集合类
静态的集合类的生命周期和应用程序的生命周期一样长,所以在程序结束前容器中的对象不能被释放,会造成内存泄露。解决办法是最好不使用静态的集合类,如果使用的话,在不需要容器时要将其赋值为null。
2.4 程序员自己写的工具有问题
2.4.1 自定义的stack【有问题】
import java.util.Arrays;
import java.util.EmptyStackException;
public class MyStack<T> {
private T[] elements;
private int size = 0;
private static final int INIT_CAPACITY = 16;
public MyStack() {
elements = (T[]) new Object[INIT_CAPACITY];
}
public void push(T elem) {
ensureCapacity();
elements[size++] = elem;
}
public T pop() {
if(size == 0)
throw new EmptyStackException();
return elements[--size];
}
private void ensureCapacity() {
if(elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}
当调用pop的时候,只是—size,数组中还有过期的对象,所以不会被gc回收。
2.4.2 JDK中的stack【没问题】
JDK中Statck底层用的是Vector。
Stack.java
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
Vector.java
public synchronized void removeElementAt(int index) {
modCount++;
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
看看人家写的,真棒:elementData[elementCount] = null; / to let gc do its work /