JAVA垃圾回收机制之外的隐患

java拥有着GC这个自动的垃圾回收机制,是否代表我们程序员就可以高枕无忧的创建对象和使用对象了吗?

下面引用一个例子解释何种情况下会产生不被GC管控和回收的对象:

package com.yyym.action;

import java.lang.reflect.Array;

import java.util.Arrays;

import java.util.EmptyStackException;

/**

* Created by yyym on 2018/12/19.

*/

public class Stack

{

private Object[] elements;

private int size;

private static final int CAPACITY_SIZE = 16;

public Stack()

{

this.elements = new Object[CAPACITY_SIZE];

}

public void push(T obj){

extendsCapacity();

elements[size++] = obj;

}

public T pop(){

if(size == 0){

throw new EmptyStackException();

}

return (T)elements[--size];

}

private void extendsCapacity(){

if(elements.length == size){

elements = Arrays.copyOf(elements,2*size+1);

}

}

}

上面这个类演示了一个简单栈的实现,初看运行起来不会有任何问题,而且问题也不容易暴露。实际上当向这个栈压入一些元素时,然后再依次弹出部分,根据栈的特性,这时候栈的游标会依次回退,代码中抽象为“--size”操作,这时候虽然游标的位置已经滑落回来,可以访问的元素(size)已经小于之前添加的元素个数,但是弹出的游标不可访达的部分元素引用还保留在栈里面,根据GC的原理可知,这些部分的引用没办法被JVM自动的释放​,所以在包含该栈的系统运转过程中,OOM(内存溢出)异常的隐患始终存在

这个问题的解决只需要依赖显示的将被弹出栈的数组引用赋值为“null”即可,这也是同类型问题的一般解决方法。以下为上面例子所做的修改:

public T pop(){

if(size == 0){

throw new EmptyStackException();

}

T element = (T) elements[--size];

elements[--size] = null;

return element;

}

结语:通俗的讲,如果的对象的引用是在客户端类中人工管理的,就是指依靠一定的逻辑管控着对象引用的生命周期,那么对象内存的回收工作也应该由人为的编码释放。在Java中只需要将对象的引用重新赋值为空即可,就能把对象的回收、清理工作返还给GC去管理

你可能感兴趣的:(JAVA垃圾回收机制之外的隐患)