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 /
