Java对象是否回收的标准是:是否有引用变量引用该对象。java
当一个对象被建立以后,GC会实时的监控每个对象的状态,包括对象的申请,引用,被引用,赋值等。当其再也不被引用时,就会被回收。数据库
若是把Java的程序看作是一个有向图,若是从运行的起点可以到达某个对象,那么它就是可达状态,不然就处于不可达状态数组
eg:缓存
参见图:性能
能够看到“第三个节点”并无被任何其余对象引用,它处于不可达状态,GC会适时的回收它。ui
三种状态:spa
为了更好的管理对象的引用,Java从1.2开始提供了三个类SoftReference,PhantomReference,WeakReference,概括起来:对象
强引用生命周期
软引用内存
弱引用
虚引用
JVM是不会回收强引用的对象,即便内存不足的时候,因此它是形成Java泄露的主要缘由。
内存泄露是指系统分配了内存,可是有些无用的内存却没有被收回,致使内存耗损愈来愈大。
虽然JVM的垃圾回收机制能够回收没有被引用的内存,可是要考虑,这个“垃圾”的含义,对于程序来讲是垃圾,由于再也不使用它们了,可是若是它们还被引用着,却对JVM来讲不是垃圾。
在ArrayList的remove方法源码中:
elementData[--size] = null;
就是为了让垃圾回收器回收的,不然就会产生内存泄露—删除了一个对象,可是该对象所占据的空间并不会被释放。
好比:
左图能够看出,ArrayList的长度为4,当删除最后一个元素的时候(即指向d的元素),若是没有elementData[--size] = null,那么它就形如右图,第四个元素已经没法被该ArrayList访问了(由于删除以后ArrayList的长度为3了),可是它仍然指向“d”,即这块内存没有被释放,gc也不会回收它,那么随着使用次数多了,内存损耗越来愈大,就形成了内存泄露。
1.尽可能只用直接量建立String(或者基础类的包装类),好比:
String str = “hello”
而不要使用String str = new String(“hello”);
虽然二者都会被JVM的字符串缓冲池缓冲,可是后者str所引用的String对象在底层还包含了一个char[]数组,该数组依次存放了h,e,l,l,o
另外,在字符串缓冲池中的字符串不会被gc回收
2.使用StringBuffer和StringBuilder,这二者是可变的。当进行字符串运算时,直接使用String,将会产生大量的临时字符串,下降性能。
3.尽早释放无用对象的引用
好比:
若是在obj = null;以后程序就执行完毕的话,这句话就没有必要书写了,由于局部变量会随着方法执行完毕而自行销毁,可是若是它后面还须要执行其余的耗时操做,那么仍是及时的将其释放。
4.尽可能少使用静态变量
由于static变量的生命周期是和类同步的,因此在类不被卸载的状况下,静态变量也会一直存储在内存中
5.不要在常常调用的方法,循环中建立java对象
这两种状况的特征是这些代码会被常常调用,若是常常建立对象,虽然对象的生命周期不长,可是系统会不断的分配,回收内存,致使性能降低。
6.缓存常常使用的对象
好比数据库链接池,一般有两种方式:
1. 使用HashMap缓冲
2. 使用开源项目
7.尽可能不要使用finalize方法
8.考虑使用软引用