在JVM运行空间中,对象的整个生命周期可以分为7个阶段:
1、创建(Creation)
2、应用(Using)
3、不可视(Invisible)
4、不可到达(Unreachable)
5、可收集(Collected)
6、终结(Finalized)
7、释放(Free)创建阶段
在该阶段,JVM通过下面的步骤完成对象的创建工作:
1、为对象分配存储空间
2、开始构造对象
3、递归调用父类的构造
4、进行对象和变量的初始化
5、调用本身的构造方法
从最强到最弱,不同的可到达性级别反映了对象的生命周期。在操作上,可将它们定义如下:强引用-Strong Reference
如果某一线程可以不必遍历所有引用对象而直接到达一个对象,则该对象是强可到达 对象。新创建的对象对于创建它的线程而言是强可到达对象。 指JVM可以通过堆内存地址直接找到相关对象的引用方式。
软引用-Soft Reference
如果一个对象不是强可到达对象,但通过遍历某一软引用可以到达它,则该对象是软可到达 对象。软引用对象,在响应内存需要时,由垃圾回收器决定是否清除此对象。软引用对象最常用于实现内存敏感的缓存。
假定垃圾回收器确定在某一时间点某个对象是软可到达对象。这时,它可以选择自动清除针对该对象的所有软引用,以及通过强引用链,从其可以到达该对象的针对任何其他软可到达对象的所有软引用。在同一时间或晚些时候,它会将那些已经向引用队列注册的新清除的软引用加入队列。
对象的所有软引用都要保证在虚拟机抛出 OutOfMemoryError 之前已经被清除。否则,清除软引用的时间或者清除不同对象的一组此类引用的顺序将不受任何约束。然而,虚拟机实现不鼓励清除最近访问或使用过的软引用。
此类的直接实例可用于实现简单缓存;该类或其派生的子类还可用于更大型的数据结构,以实现更复杂的缓存。只要软引用的指示对象是强可到达对象,即正在实际使用的对象,就不会清除软引用。例如,通过保持最近使用的项的强指示对象,并由垃圾回收器决定是否放弃剩余的项,复杂的缓存可以防止放弃最近使用的项。
具有较强的引用功能。只有当内存不够的时候,才回收这类内存。
软引用还可以在java抛出OutOfMemory之前将对象置为NULL。
来看一个例子:public static void main(String[] args) { A a = new A(); // 使用a // 创建引用给定对象的新的软引用 SoftReference<A> sr = new SoftReference<A>(a); //a = null; // 再次使用 if (a != null) { a=sr.get();//得到对象 System.out.println("继续使用中。。。。。。。"); }else{ a=new A(); sr=new SoftReference<A>(a); System.out.println("再次创建。。。。。。"); } }
弱引用-Weak Reference
如果一个对象既不是强可到达对象,也不是软可到达对象,但通过遍历弱引用可以到达它,则该对象是弱可到达 对象。当清除对某一弱可到达对象的弱引用时,便可以终止此对象了。例子:
public static void main(String[] args) { A a=new A(); WeakReference<A> wr=new WeakReference<A>(a); a=null; if(a!=null){ a=wr.get(); }else{ a=new A(); wr=new WeakReference<A>(a); } }
虚引用-Phantom Reference如果一个对象既不是强可到达对象,也不是软可到达对象或弱可到达对象,它已经终止,并且某个虚引用在引用它,则该对象是虚可到达 对象。
最后,当不能以上述任何方法到达某一对象时,该对象是不可到达 对象,因此可以回收此对象。
虚引用对象,在回收器确定其指示对象可另外回收之后,被加入队列。虚引用最常见的用法是以某种可能比使用 Java 终结机制更灵活的方式来指派 pre-mortem 清除动作。如果垃圾回收器确定在某一特定时间点上虚引用的指示对象是虚可到达对象,那么在那时或者在以后的某一时间,它会将该引用加入队列。
为了确保可回收的对象仍然保持原状,虚引用的指示对象不能被获取:虚引用的 get 方法总是返回 null。
与软引用和弱引用不同,虚引用在加入队列时并没有通过垃圾回收器自动清除。通过虚引用可到达的对象将仍然保持原状,直到所有这类引用都被清除,或者它们都变得不可到达。
在实际的开发中一般很少使用弱引用与虚引用,使用软引用的情况较多,这是因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出等问题的产生。
当对象经历了应用阶段之后,那么该对象便处于不可视阶段,其强引用已经消失。
如果一个对象已经使用完毕,而且在其可视区域不再使用,此时应主动将对象设置为空,以便通知JVM及时发现这个垃圾对象。例子:
public static void main(String[] args) { A a=new A(); a.doSomeThing();//使用 //.....’使用完毕 //a=null; try{ a.doSomeThing(); }catch(Exception ex){ ex.printStackTrace(); } }
JVM中的对象引用类型
最新推荐文章于 2022-02-14 22:37:26 发布