热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java必备:对象与垃圾回收

一、垃圾回收特征 垃圾回收机制只负责回收内存中的对象,不会回收任何物理资源(例如数据库连接、网络IO等资源); 程序无法精确控制垃圾回收的运行,垃圾回收会在合适的时候

一、垃圾回收特征 


  • 垃圾回收机制只负责回收内存中的对象,不会回收任何物理资源(例如数据库连接、网络IO等资源); 

  • 程序无法精确控制垃圾回收的运行,垃圾回收会在合适的时候进行。当对象永久地失去引用后,系统就会在合适的时候回收它所占有的内存 

  • 垃圾回收机制回收任何对象执之前,总会调用finalize()方法,该方法可能是该对象重新复活(然一个引用变量重新引用该对象),从而导致垃圾回收机制取消回收 


 



二、对象在内存中的状态 


  • 当一个对象在堆内存中运行的时候,根据它被引用变量所引用的状态,可以把所处的状态分成如下三种 


    • 可达状态:当一个对象被创建后,弱有一个以上的引用变量引用它,则这个对象在程序中处于可达状态,程序可以通过变量调用该对象的Field和方法; 

    • 可恢复状态 


      • 如果程序的某个对象不再由任何引用变量引用它,它就进入到可恢复状态 

      • 这这个状态下,系统的垃圾回收机制准备回收该对象所占有的内存,在回收该对象之前,系统会调用所有可恢复状态对象的finalize()方法进行资源清理 

      • 如果系统在调用finalize()方法是重新让一个引用变量引用该对象,则这个对象会再次变成可达状态;否则对象进如不可达状态 


    • 不可达状态 


      • 当对象和所有引用的关联都被切断,且系统已经调用所有对象的finalize()方法后依然没有使该对象变成可达状态,那么这个对象永久性地失去引用,最后变成不可达状态 

      • 当一个对象处于不可达状态,系统才会真正回收该对象的所有资源 


       



  • 当某个对象被其他类的类变量引用时,只有该类被销毁后,该对象才会进入可恢复状态;当某个对象被其他类的实例变量引用时,只有当该对象被销毁后,该对象才会进入可恢复状态; 


 



三、强制垃圾回收 


  • 当一个对象失去引用后,系统何时调用它的finalize()方法对它进行资源清理,何时她会变成不可达状态,系统核实何时回收它占有的内存,对程序完全透明;程序只能控制一个对象何时不再被任何引用变量引用,觉不能控制它何时被回收; 


 



  • 程序无法控制Java垃圾回收的时机,但是我们依然可以强制系统进行垃圾回收这种强制只是通知系统进行垃圾回收,但系统是否进行垃圾回收依然不确定 

  • 垃圾回收机制也不会对程序的建议完全置之不理,垃圾回收机制会在收到通知后,尽快进行垃圾回收 


 



  • 强制垃圾回收有如下两个方法 


    • 调用System类的gc()静态方法 

    • 调用Runtime对象的gc()实例方法 




 


四、finalize方法 


  • 在垃圾回收机制回收某个对象所占用的内存之前,通常要求程序调用适当的方法来清理资源,在没有明确指定清理资源的情况下,Java提供了默认机制类清理该对象的资源,这个机制就是finalize()方法 


protected
void finalize() throws 
Throwable;
 


 



  • 当finalize()方法返回后,对象消失,垃圾回收机制开始执行 


 



  • 如果程序终止之前没有进行垃圾回收,则不会调用失去引用独对象的finalize()方法来清理资源。垃圾回收机制何时调用对象的finalize()方法是完全透明的,只有当程序认为需要更多地额外的内存是,垃圾回收机制才调用 


 



  • finalize()方法有如下4个特点: 


    • 永远不要调用某个对象的finalize()方法,该方法应交给垃圾回收机制调用 

    • finalize()方法何时被调用,是否被调用具有不确定性,不要把finalize()方法当成一定会执行的方法 

    • 当JVM执行可恢复对象的finalize()方法时,可能使该对象或系统中其他对象重新变成可达状态 

    • 当JVM执行finalize()方法时出现异常时,垃圾回收机制不会报告异常,程序继续执行 


     


  • 由于finalize()方法并不一定会被执行,因此如果清理某个类里打开的资源,则不要放在finalize()方法中进行清理 


 



  • System和Runtime类里提供了一个runFinalization方法,可以强制垃圾回收机制调用系统中可恢复对象的finalize()方法 



 


五、对象的软、弱和虚引用 


  • Java语言对对象的引用如下4中方式: 


    • 强引用(StrongReference): 


      • 最常见的引用方式,创建一个对象,并把这个对象赋值给一个引用变量,程序通过该引用变量来操作实际的对象 

      • 当一个对象被一个或一个以上的引用变量所引用时,它处于可达状态,不可能被系统的垃圾回收机制回收 


    • 软引用(SoftReference): 


      • 需要通过SoftReference来实现,当一个对象只有软引用的时,它又可能被来及回收机制回收 

      • 对于只有软引用的对象而言,当系统内存空间足够的时候,它不会被系统回收,程序也可以引用该对象;当系统内存空间不足的时候,系统可能会回收它; 

      • 通常用于内存敏感的程序中 


    • 弱引用(WeakReference): 


      • 通过WeakReference类实现,弱引用和软引用很像,但是弱引用的级别耕地 

      • 对于只有弱引用的对象而言,当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存 

      • 当然并不是说当一个对象只有弱引用时,它就会立即回收正如那些失去引用的对象一样,必须等到系统垃圾回收机制运行时才会被回收 


    • 虚引用(PhantomReference): 


      • 通过PhantomReference类实现,虚引用类似于没有引用 

      • 虚引用对对象本身没有太大的影响,对象甚至感觉不到虚引用的存在,如果一个对象只有一个虚引用,那么它和没有应用的效果大致相同 

      • 它的主要作用用于跟踪对象被垃圾回收的状态,虚引用不能单独使用,虚引用必须和引用队列(ReferenceQueue)联合使用 


       



  • 上面三个引用类都包含了一个get方法,用于获取被它们引用的对象 


 



  • 引用队列由java.lang.ref.ReferenceQueue类表示,它用于保存被内存回收后对象的引用 


    • 当联合使用软引用、弱引用和引用队列时,系统在回收内存对象之后,将把被回收的对象对应的引用天天加到关联的引用队列中 

    • 与软引用和弱引用不同的是,虚引用在对象被释放之前,将把它对应的虚引用添加到它关联的引用队列中,这使得可以在对象被回收之前采取行动; 


     


  • 软引用和虚引用可以单独使用,虚引用不能单独使用,单独使用虚引用没有太大的意义 


    • 虚引用的主要作用就是跟踪对象被垃圾回收的状态,程序可以通过检查与虚引用关联的引用队列中是否已经包含了虚引用,从而了解虚引用的对象是否立即将被回收; 


     


  • 使用这些引用类可以避免在程序执行期间将对象保留在内存中。如果以软引用、弱引用或虚引用的方式引用对象,垃圾收集器旧能够随意地释放对象;如果希望尽可能减小程序在其生命周期中所占用的内存大小时,这些引用类就很有用途; 


 



  • 必须指出:要使用这些特殊的引用类,就不能保留对对象的强引用;如果保留了对象的强引用,旧会浪费这些引用类所提供的任何好处 



推荐阅读
  • Unity3D 中 AsyncOperation 实现异步场景加载及进度显示优化技巧
    在Unity3D中,通过使用`AsyncOperation`可以实现高效的异步场景加载,并结合进度条显示来提升用户体验。本文详细介绍了如何利用`AsyncOperation`进行异步加载,并提供了优化技巧,包括进度条的动态更新和加载过程中的性能优化方法。此外,还探讨了如何处理加载过程中可能出现的异常情况,确保加载过程的稳定性和可靠性。 ... [详细]
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 在使用Eclipse进行调试时,如果遇到未解析的断点(unresolved breakpoint)并显示“未加载符号表,请使用‘file’命令加载目标文件以进行调试”的错误提示,这通常是因为调试器未能正确加载符号表。解决此问题的方法是通过GDB的`file`命令手动加载目标文件,以便调试器能够识别和解析断点。具体操作为在GDB命令行中输入 `(gdb) file `。这一步骤确保了调试环境能够正确访问和解析程序中的符号信息,从而实现有效的调试。 ... [详细]
  • MySQL的查询执行流程涉及多个关键组件,包括连接器、查询缓存、分析器和优化器。在服务层,连接器负责建立与客户端的连接,查询缓存用于存储和检索常用查询结果,以提高性能。分析器则解析SQL语句,生成语法树,而优化器负责选择最优的查询执行计划。这一流程确保了MySQL能够高效地处理各种复杂的查询请求。 ... [详细]
  • 本项目通过Python编程实现了一个简单的汇率转换器v1.02。主要内容包括:1. Python的基本语法元素:(1)缩进:用于表示代码的层次结构,是Python中定义程序框架的唯一方式;(2)注释:提供开发者说明信息,不参与实际运行,通常每个代码块添加一个注释;(3)常量和变量:用于存储和操作数据,是程序执行过程中的重要组成部分。此外,项目还涉及了函数定义、用户输入处理和异常捕获等高级特性,以确保程序的健壮性和易用性。 ... [详细]
  • VS2019 在创建 Windows 恢复点时出现卡顿问题及解决方法
    在使用 Visual Studio 2019 时,有时会在创建 Windows 恢复点时遇到卡顿问题。这可能是由于频繁的自动更新导致的,每次更新文件大小可能达到 1-2GB。尽管现代网络速度较快,但这些更新仍可能对系统性能产生影响。本文将探讨该问题的原因,并提供有效的解决方法,帮助用户提升开发效率。 ... [详细]
  • 为了提升单位内部沟通效率,我们开发了一套飞秋软件与OA系统的消息接口服务系统。该系统能够将OA系统中的审批、通知等信息自动同步至飞秋平台,确保员工在使用飞秋进行日常沟通的同时,也能及时获取OA系统的各类重要信息,从而实现无缝对接,提高工作效率。 ... [详细]
  • 深入解析:Synchronized 关键字在 Java 中对 int 和 Integer 对象的作用与影响
    深入探讨了 `Synchronized` 关键字在 Java 中对 `int` 和 `Integer` 对象的影响。尽管初看此题似乎简单,但其实质在于理解对象的概念。根据《Java编程思想》第二章的观点,一切皆为对象。本文详细分析了 `Synchronized` 关键字在不同数据类型上的作用机制,特别是对基本数据类型 `int` 和包装类 `Integer` 的区别处理,帮助读者深入理解 Java 中的同步机制及其在多线程环境中的应用。 ... [详细]
  • Vim 编辑器功能强大,但其默认的配色方案往往不尽如人意,尤其是注释颜色为蓝色时,对眼睛极为不友好。为了提升编程体验,自定义配色方案显得尤为重要。通过合理调整颜色,不仅可以减轻视觉疲劳,还能显著提高编码效率和兴趣。 ... [详细]
  • 在 Mac 上查看隐藏文件和文件夹的详细指南。通过终端命令,您可以轻松地显示或隐藏这些文件。具体步骤如下:输入 `defaults write com.apple.finder AppleShowAllFiles -bool true` 以显示所有隐藏文件,或使用 `defaults write com.apple.finder AppleShowAllFiles -bool false` 以重新隐藏它们。此方法适用于各种版本的 macOS,帮助用户更好地管理和访问系统文件。 ... [详细]
  • 本文详细解析了逻辑运算符“与”(&&)和“或”(||)在编程中的应用。通过具体示例,如 `[dehua@teacher~]$[$(id -u) -eq 0] && echo "You are root" || echo "You must be root"`,展示了如何利用这些运算符进行条件判断和命令执行。此外,文章还探讨了这些运算符在不同编程语言中的实现和最佳实践,帮助读者更好地理解和运用逻辑运算符。 ... [详细]
  • 二分查找算法详解与应用分析:本文深入探讨了二分查找算法的实现细节及其在实际问题中的应用。通过定义 `binary_search` 函数,详细介绍了算法的逻辑流程,包括初始化上下界、循环条件以及中间值的计算方法。此外,还讨论了该算法的时间复杂度和空间复杂度,并提供了多个应用场景示例,帮助读者更好地理解和掌握这一高效查找技术。 ... [详细]
  • 在 Android 开发中,`android:exported` 属性用于控制组件(如 Activity、Service、BroadcastReceiver 和 ContentProvider)是否可以被其他应用组件访问或与其交互。若将此属性设为 `true`,则允许外部应用调用或与之交互;反之,若设为 `false`,则仅限于同一应用内的组件进行访问。这一属性对于确保应用的安全性和隐私保护至关重要。 ... [详细]
  • 蚂蚁课堂:性能测试工具深度解析——JMeter应用与实践
    蚂蚁课堂:性能测试工具深度解析——JMeter应用与实践 ... [详细]
  • 在 iOS 开发中,经常会遇到 `@(YES)`、`@[firstViewController]` 以及 `@{@a:@b}` 这样的语法糖。这些简化的写法分别用于初始化布尔值、数组和字典对象,能够显著提高代码的可读性和编写效率。例如,`@(YES)` 可以快速创建一个布尔值对象,`@[firstViewController]` 则用于创建包含单个元素的数组,而 `@{@a:@b}` 则用于创建键值对字典。理解这些语法糖的使用方法,有助于开发者更加高效地进行编码。 ... [详细]
author-avatar
鲁尼杰
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有