资源预览内容
第1页 / 共4页
第2页 / 共4页
第3页 / 共4页
第4页 / 共4页
亲,该文档总共4页全部预览完了,如果喜欢就下载吧!
资源描述
Java 中的中的垃圾回收垃圾回收与与对象对象生命周期生命周期1. 垃圾回收垃圾回收 垃圾回收垃圾回收是 Java 程序设计中内存管理的核心概念,JVM 的内存管理机制被称为垃圾回收垃圾回收机制。 一个一个对象对象创建后被放置在创建后被放置在 JVM 的堆内存中,当永远不再引用这个的堆内存中,当永远不再引用这个对象对象时,它将被时,它将被 JVM 在堆内存中回收。被创建的在堆内存中回收。被创建的对象对象不能再生,同时也没有办法通过程不能再生,同时也没有办法通过程序语句释放它们。即当序语句释放它们。即当对象对象在在 JVM 运行空间中无法通过根集合到达运行空间中无法通过根集合到达(找到找到)时时,这个这个对象对象被称为垃圾被称为垃圾对象对象。根集合是由类中的静态引用域与本地引用域组成的。根集合是由类中的静态引用域与本地引用域组成的。JVM 通过根集合索引通过根集合索引对象对象。 在做在做 Java 应用开发时经常会用到由应用开发时经常会用到由 JVM 管理的两种类型的内存管理的两种类型的内存:堆内存和栈内存。简单来讲,堆内存主要用来存储程序在运行时创建或实例化的堆内存和栈内存。简单来讲,堆内存主要用来存储程序在运行时创建或实例化的对象对象与与变量。例如通过变量。例如通过 new 关键字创建的关键字创建的对象对象。而栈内存则是用来存储程序代码中声明为静态或非静态的方法。而栈内存则是用来存储程序代码中声明为静态或非静态的方法。 (1) 堆内存堆内存 堆内存在堆内存在 JVM 启动的时候被创建,堆内存中所存储的启动的时候被创建,堆内存中所存储的对象对象可以被可以被 JVM 自动回收,不能通过其他外部手段回收,也就是说开发人员无法通过添加相关代码自动回收,不能通过其他外部手段回收,也就是说开发人员无法通过添加相关代码的手段来回收堆内存中的的手段来回收堆内存中的对象对象。堆内存通常情况下被分为两个区域。堆内存通常情况下被分为两个区域:新新对象对象区域与老区域与老对象对象区域。区域。 新新对象对象区域区域:又可细分为三个小区域又可细分为三个小区域:伊甸园区域、伊甸园区域、From 区域与区域与 To 区域。伊甸园区域用来保存新创建的区域。伊甸园区域用来保存新创建的对象对象,它就像一个堆栈,新的,它就像一个堆栈,新的对象对象被创建,就像被创建,就像指向该栈的指针在增长一样,当伊甸园区域中的指向该栈的指针在增长一样,当伊甸园区域中的对象对象满了之后,满了之后,JVM 系统将要做到可达性测试,主要任务是检测有哪些系统将要做到可达性测试,主要任务是检测有哪些对象对象由根集合出发是不可达的,这些由根集合出发是不可达的,这些对象对象就可以被就可以被 JVM 回收,并且将所有的活动回收,并且将所有的活动对象对象从伊甸园区域拷贝到从伊甸园区域拷贝到 To 区域,此时一些区域,此时一些对象对象将发生状态交换,有的将发生状态交换,有的对象对象就从就从 To 区域被转移到区域被转移到 From 区域,区域,此时此时 From 区域就有了区域就有了对象对象。上面。上面对象对象迁移的整个过程,都是由迁移的整个过程,都是由 JVM 控制完成的。控制完成的。 老老对象对象区域区域:在老在老对象对象区域中的区域中的对象对象仍然会有一个较长的生命周期,大多数的仍然会有一个较长的生命周期,大多数的 JVM 系统垃圾系统垃圾对象对象,都是源于,都是源于“短命短命“对象对象,经过一段时间后,被转入老,经过一段时间后,被转入老对象对象区域的区域的对象对象,就变成了垃圾,就变成了垃圾对象对象。此时,它们都被打上相应的标记,。此时,它们都被打上相应的标记,JVM 系统将会自动回收这些垃圾系统将会自动回收这些垃圾对象对象,建议不要频繁地,建议不要频繁地强制强制系统作垃圾回收,这是因为系统作垃圾回收,这是因为JVM 会利用有限的系统资源,优先完成垃圾回收工作,导致应用无法快速地响应来自用户端的请求,这样会影响系统的整体性能。会利用有限的系统资源,优先完成垃圾回收工作,导致应用无法快速地响应来自用户端的请求,这样会影响系统的整体性能。 (2) 栈内存栈内存 堆内存主要用来存储程序在运行时创建或实例化的对象与变量。例如通过 new 关键字创建的对象。而栈内存则是用来存储程序代码中声明为静态或非静态的方法。 2. JVM 中对象的生命周期中对象的生命周期 在 JVM 运行空间中,对象的整个生命周期大致可以分为 7 个阶段: 创建阶段创建阶段; 应用阶段应用阶段; 不可视阶段不可视阶段; 不可到达阶段不可到达阶段; 可收集阶段可收集阶段; 终结阶段终结阶段; 释放阶段释放阶段 上面这 7 个阶段,构成了 JVM 中对象的完整的生命周期。 (1) 创建阶段创建阶段 在对象的创建阶段,系统主要通过下面的步骤,完成对象的创建过程: 为对象分配存储空间为对象分配存储空间; 开始构造对象开始构造对象; 从超类到子类对从超类到子类对 static 成员进行初始化成员进行初始化; 超类成员变量按顺序初始化,递归调用超类的构造方法超类成员变量按顺序初始化,递归调用超类的构造方法; 子类成员变量按顺序初始化,子类构造方法调用。子类成员变量按顺序初始化,子类构造方法调用。 在创建对象时应注意几个关键应用规则在创建对象时应注意几个关键应用规则: 避免在循环体中创建对象,即使该对象占用内存空间不大。避免在循环体中创建对象,即使该对象占用内存空间不大。 尽量及时使对象符合垃圾回收标准。比如尽量及时使对象符合垃圾回收标准。比如 myObject = null。 不要采用过深的继承层次。不要采用过深的继承层次。 访问本地变量优于访问类中的变量。访问本地变量优于访问类中的变量。(2) 应用阶段 在对象的引用阶段,对象具备如下特征: 系统至少维护着对象的一个强引用系统至少维护着对象的一个强引用(Strong Reference); 所有对该对象的引用全部是强引用所有对该对象的引用全部是强引用(除非我们显示地适用了除非我们显示地适用了:软引用软引用(Soft Reference)、弱引用、弱引用(Weak Reference)或虚引用或虚引用(Phantom Reference). 强引用强引用(Strong Reference):是指是指 JVM 内存管理器从根引用集合出发遍历堆中所有到达对象的路径。当到达某对象的任意路径都不含有引用对象时,内存管理器从根引用集合出发遍历堆中所有到达对象的路径。当到达某对象的任意路径都不含有引用对象时,这个对象的引用就被称为强引用。这个对象的引用就被称为强引用。 软引用软引用(Soft Reference):软引用的主要特点是有较强的引用功能。只有当内存不够的时候,才回收这类内存,因此内存足够时它们通常不被回收。软引用的主要特点是有较强的引用功能。只有当内存不够的时候,才回收这类内存,因此内存足够时它们通常不被回收。另外这些引用对象还能保证在另外这些引用对象还能保证在 Java 抛出抛出 OutOfMemory 异常之前,被设置为异常之前,被设置为 null。它可以用于实现一些常用资源的缓存,实现。它可以用于实现一些常用资源的缓存,实现 Cache 功能,保证最大功能,保证最大限度地使用内存你而不引起限度地使用内存你而不引起 OutOfMemory。下面是软引用的实现代码: import java.lang.ref.SoftReference; . A a = new A(); . / 使用 a . / 使用完了 a, 将它设置为 soft 引用类型,并且释放强引用SoftReference sr = new SoftReference(a); a = null; . / 下次使用时 if (sr != null) a = sr.get(); else / GC 由于低内存,已释放 a,因此需要重新装载 a = new A(); sr = new SoftReference(a); 软引用技术的引进使 Java 应用可以更好地管理内存,稳定系统,防止系统内存溢出,避免系统崩溃。因此在处理一些占用内存较大且生命周期较长,但使用并不繁地对象时应尽量应用该技术。提高系统稳定性。 弱引用弱引用(Weak Reference):弱应用对象与软引用对象的最大不同就在于弱应用对象与软引用对象的最大不同就在于:GC 在进行垃圾回收时,需要通过算法检查是否回收在进行垃圾回收时,需要通过算法检查是否回收 Soft 应用对象,而对于应用对象,而对于Weak 引用,引用,GC 总是进行回收。总是进行回收。Weak 引用对象更容易、更快地被引用对象更容易、更快地被 GC 回收。回收。Weak 引用对象常常用于引用对象常常用于 Map 结构中。结构中。import java.lang.ref.WeakReference; 4. . 5. 6. A a = new A(); 7. . 8. 9. / 使用 a 10. . 11. 12. / 使用完了 a, 将它设置为 Weak 引用类型,并且释放强引用 13. WeakReference wr = new WeakReference(a); 14. a = null; 15. . 16. 17. / 下次使用时 18. if (wr != null) 19. a = wr.get(); 20. else 21. a = new A(); 22. wr = new WeakReference(a); 23. 虚引用虚引用(Phantom Reference): 虚引用的用途较少,主要用于辅助虚引用的用途较少,主要用于辅助 finalize 函数的使用。函数的使用。 虚引用虚引用(Phantom Reference)对象指一些执行完了对象指一些执行完了 finalize 函数,并为不可达对象,但是还没有被函数,并为不可达对象,但是还没有被 GC 回收的对象。这种对象可以辅助回收的对象。这种对象可以辅助 finalize 进行进行一些后期的回收工作,我们通过覆盖了一些后期的回收工作,我们通过覆盖了 Refernce 的的 clear()方法,增强资源回收机制的灵活性。方法,增强资源回收机制的灵活性。 在实际程序设计中一般很少使用弱引用和虚引用,是用软引用的情况较多,因为软引用可以加速 JVM 对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生。 (3) 不可视阶段不可视阶段 当一个对象处于不可视阶段,说明我们在其他区域的代码中已经不可以在引用它,其强引用已经消失,例如,本地变量超出了其可视 的范围。 1.try 2. Object localObj = new Object(); 3. localObj.doSomething(); 4. catch (Exception e) 5. e.printStackTrace(); 6. 7. 8. if (true) 9. / 此区域中 localObj 对象已经不可视了, 编译器会报错。 10. localObj.doSomething(); 11. (4) 不可到达阶段不可到达阶段 处于不可达阶段的对象在虚拟机的对象引用根集合中再也找不到直接或间接地强引用,这些对象一般是所有线程栈中的临时变量。所有已经装载的静态变量或者是对本地代码接口的引用。 (5) 可收集阶段、终结阶段与释放阶段可收集阶段、终结阶段与释放阶段 当一个对象处于可收集阶段、终结阶段与释放阶段时,该对象有如下三种情况: 回收器发现该对象已经不可达。 finalize 方法已经被执行。 对象空间已被重用。
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号