Java对象与垃圾回收
2014-05-17 17:01
351 查看
Java中创建引用类型对象时,都会在堆内存中分配一块区域,Java对象就保存在这块内存区域中,当这块内存区域不再被任何变量引用时,垃圾回收机制就会把这块内存区域回收。
垃圾回收机制根据回收策略运行,程序无法精确控制。
在回收Java对象之前,会先调用该对象的finalize()方法。
可达状态:Java对象被创建后,如果被一个或多个变量引用,那么这个Java对象处于可达状态,即这个对象可以被访问。
可恢复状态:Java对象不再被任何变量引用就进入了可恢复状态。在这种状态下,垃圾回收机制准备回收该对象所占用的资源,在回收该对象之前,该对象的finalize()方法进行资源清理。如果在finalize()方法中重新让变量引用该对象,则该对象再次变为可达状态,否则该对象进入不可达状态。
不可达状态:Java对象不被任何变量引用,且系统在调用对象的finalize()方法后依然没有使该对象变成可达状态(该对象依然没有被变量引用),那么该对象将变成不可达状态。当Java对象处于不可达状态时,系统才会真正回收该对象所占有的资源。
不要主动调用finalize()方法,该方法应该交给垃圾回收机制调用。
finalize()方法无法确定何时被调用,因此finalize()方法不一定会执行。
当JVM(Java虚拟机)调用finalize()方法时,可能使该对象变成可达状态。
当JVM(Java虚拟机)调用finalize()出现异常时,垃圾回收机制不会报告异常,程序继续执行。
1 垃圾回收机制的特征
垃圾回收机制只负责回收堆内存中的对象。垃圾回收机制根据回收策略运行,程序无法精确控制。
在回收Java对象之前,会先调用该对象的finalize()方法。
2 Java对象在内存中的状态
Java对象在堆中运行时有三种状态:可达状态、可恢复状态、不可达状态。可达状态:Java对象被创建后,如果被一个或多个变量引用,那么这个Java对象处于可达状态,即这个对象可以被访问。
可恢复状态:Java对象不再被任何变量引用就进入了可恢复状态。在这种状态下,垃圾回收机制准备回收该对象所占用的资源,在回收该对象之前,该对象的finalize()方法进行资源清理。如果在finalize()方法中重新让变量引用该对象,则该对象再次变为可达状态,否则该对象进入不可达状态。
不可达状态:Java对象不被任何变量引用,且系统在调用对象的finalize()方法后依然没有使该对象变成可达状态(该对象依然没有被变量引用),那么该对象将变成不可达状态。当Java对象处于不可达状态时,系统才会真正回收该对象所占有的资源。
3 强制垃圾回收
Java程序无法精确控制Java垃圾回收的时机,但是依然可以强制进行垃圾回收,也就是通知系统进行垃圾回收,但系统何时进行垃圾回收无法确定。不过垃圾回收机制也不会对程序的垃圾回收命令完全不理,垃圾回收机制在收到通知后会尽快进行垃圾回收。强制垃圾回收有两种方法:①调用System类的gc()静态方法。②调用Runtim对象的gc()实例方法。public class GcDemo { private int index; public GcDemo(int index){ this.index = index; } public static void main(String[] args) { for(int i = 0; i < 5; i++){ new GcDemo(i); //下面两行代码的作用完全相同,强制系统进行垃圾回收 //Runtime.getRuntime().gc(); System.gc(); } } public void finalize(){ System.out.println("正在清理第 " + index + "个GcDemo..."); } } /* 程序执行的结果如下: 正在清理第 3个GcDemo... 正在清理第 0个GcDemo... 正在清理第 1个GcDemo... 正在清理第 2个GcDemo... 正在清理第 4个GcDemo... 垃圾回收并不是严格按照顺序执行的,也就是说垃圾回收不是实时的,而是根据垃圾回收机制在合适的时间触发。 */
4 finalize()方法
在回收Java对象占用的内存之前,通常会调用适当的方法清理资源,默认情况下会调用finalize()方法来清理该对象的资源。finalize()方法在Object类中定义,在finalize()方法被调用后,垃圾回收机制开始执行。Object类的finalize()方法可以在继承类中重写(Override),用来清理继承类的资源。finalize()方法具有以下特点:不要主动调用finalize()方法,该方法应该交给垃圾回收机制调用。
finalize()方法无法确定何时被调用,因此finalize()方法不一定会执行。
当JVM(Java虚拟机)调用finalize()方法时,可能使该对象变成可达状态。
当JVM(Java虚拟机)调用finalize()出现异常时,垃圾回收机制不会报告异常,程序继续执行。
public class FinalizeDemo { private static FinalizeDemo fd = null; private int index; public FinalizeDemo(int index){ this.index = index; } public void print(){ System.out.println("FinalizeDemo " + index); } public static void main(String[] args) throws InterruptedException { new FinalizeDemo(5); System.gc(); //暂停2秒,以便系统进行垃圾回收。 //如果不执行①语句,那么②语句会比finalize方法先执行,这时FinalizeDemo.fd还未赋值。 Thread.sleep(2000); //① try{ FinalizeDemo.fd.print(); //② }catch(Exception e){ System.out.println("Error:" + new Date().getTime()); } } public void finalize(){ System.out.println("正在清理FinalizeDemo " + index + " :" + new Date().getTime()); fd = this; } } /* 程序执行的结果如下: 正在清理FinalizeDemo 5 :1400316264637 FinalizeDemo 5 垃圾回收先执行finalize()方法,然后把对象赋给FinalizeDemo.fd。 如果把①语句注释掉,程序执行结果如下: Error:1400316599948 正在清理FinalizeDemo 5 :1400316599948 发现②语句会比finalize()方法先执行,也就是还没有进行垃圾回收,②语句就已经执行了。 */
相关文章推荐
- 4、如何强制垃圾回收一个对象?(java)
- Java垃圾回收精粹——权衡点、对象生命周期以及全局暂停事件
- Java 对象与垃圾回收
- java方法中把对象置null,到底能不能加速垃圾回收
- Java中的垃圾回收问题以及在创建对象的时候的内存的分析
- java垃圾回收之对象生存or死亡
- java 之 对象与垃圾回收
- [Think In Java]基础拾遗1 - 对象初始化、垃圾回收器、继承、组合、代理、接口、抽象类
- Java——对象与垃圾回收
- Java基础之(二十六)对象与垃圾回收
- java中的对象和垃圾回收
- Java对象的生命周期与垃圾回收以及四种引用
- Java必备:对象与垃圾回收
- 面向对象_引用类型_内存分析_垃圾回收JAVA028-033
- Java中的垃圾回收与对象生命周期
- JAVA 对象被垃圾回收后其成员变量可用吗?
- java 图解JVM在内存中申请对象及垃圾回收流程
- java 垃圾回收步步深入02----判断对象是否已死
- Java对象与垃圾回收
- Java对象的引用与垃圾回收