Java垃圾收集学习笔记

Java垃圾收集学习笔记

(1)除了释放不再被引用的对象,垃圾收集器还要处理堆碎块。请求分配新对象时可能不得不增大堆空间的大小,虽然可以使用的空闲空间是足够的,但是堆中没有没有连续的空间放得下新对象。可能会导致虚拟机产生不必要的”内存不足“错误。

(2)使用垃圾收集堆,有一个潜在的缺陷就是加大程序的负担,可能影响程序的性能。因为虚拟机需要追踪哪些对象被正在执行的程序引用,还要动态释放垃圾对象。

(3)程序可以调用System.gc()建议jvm去收集垃圾, 但是不能为垃圾回收机制指定某个对象是不是垃圾。即便调用了gc()并不会马上进行垃圾回收甚至不一定会执行垃圾回收。所有的内存分配和回收权限都在jvm,不在开发人员手里。

可以试试:

public class RubbishRelease {
    // 类的finalize方法,可以告诉垃圾回收器应该执行的操作,该方法从Object类继承而来。
    // 在从堆中永久删除对象之前,垃圾回收器调用该对象的finalize方法。
    public void finalize() {
        System.out.println("the Object is going...");
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            // 下面不断创建对象,但是这些对象都没有被引用
            new RubbishRelease();
            new RubbishRelease();
            new RubbishRelease();
            System.gc();
        }
        System.out.println("The program is over!");
    }
}

运行结果:

这里写图片描述

(4)垃圾收集算法有很多,但任何垃圾收集算法都必须做两件事情。首先,它必须检测出垃圾对象。其次,它必须回收垃圾对象所使用的堆空间并还给程序

(5)区分活动对象和垃圾的两个基本方法是引用计数跟踪

(6)引用计数是垃圾收集的早期策略。在这种方法中,堆中每一个对象都有一个引用计数。一个对象被创建了,并且指向该对象的引用被分配给一个变量,这个对象的引用计数被置为1。当任何其他变量被赋值为对这个对象的引用时,计数加1。当一个对象的引用超过了生存期或者被设置一个新的值时,对象的引用计数减1。任何引用计数为0的对象可以被当作垃圾收集。当一个对象被垃圾收集的时候,它引用的任何对象计数值减1。这种方法的好处是,引用计数收集器可以很快地执行,交织在程序的运行之中。这个特性对于程序不能被长时间打断的实时环境很有利。坏处就是,引用计数无法检测出循环(即两个或者更多的对象互相引用)。

(7)跟踪收集器追踪从根节点开始的对象引用图。给追踪过程中遇到对象以某种方式打上标记。追踪结束时,未被标记的对象就是无法触及的,从而被收集。基本的追踪算法被称作“标记并清除”,这个名字指出垃圾收集过程的两个阶段。

(8)Java虚拟机的垃圾收集器可能有对付堆碎块的策略。标记并清除收集器通常使用的两种策略是压缩拷贝。这两种方法都是快速地移动对象来减少堆碎块。

(9)压缩收集器把活动的对象越过空闲区滑动到堆的一端,在这个过程中,堆的另一端出现一个大的连续空闲区。所有被移动的对象的引用也被更新,指向新的位置。

(10)拷贝收集器把所有的活动的对象移动到一个新的区域。在拷贝过程中,被紧挨着布置,这样可以消除原本它们在旧区域的空隙。即空闲区。一般的拷贝收集器算法被称为“停止并拷贝”。此方案中,堆被分成两个区域,任何时候都使用一个区域。对象在同一个区域中分配直到被耗尽。此时,程序执行被中止,堆被遍历,遍历时遇到活动的对象被拷贝到另个区域。当停止和拷贝过程结束时,程序恢复执行。依次往复,对于指定大小的堆来说需要两倍大小的内存,由于任何时候都只使用其中的一半,这就是该方法带来的代价。

(11)按代收集:根据对象的存活周期(一次垃圾收集为一个周期)的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用拷贝算法,只需要付出少量存活对象的拷贝成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,可以使用“标记并清除”算法。

(12)终结方法(finalize),这个在上面第3点也有提到:这个方法是垃圾收集器在释放对象前必须运行。这个可能存在的终结方法使得任何Java虚拟机的垃圾收集器要完成的工作更加复杂。因为终结方法可能“复活”了某些不再被引用的对象(本身或者其他对象)。

(13)中的每一个对象都有三种状态之一:可触及的可复活的以及不可触及的可触及状态好理解。关于可复活状态:它在从根节点开始的追踪图中不可触及,但是又可能在垃圾收集器执行某些终结方法时触及。不仅仅是那些声明了finalize方法的对象,而是所有的对象都要经过可复活状态。而不可触及状态标志着不但对象不再被触及,而且也不可能通过任何终结方法复活。不可触及的对象不再对程序的执行产生影响,可自由地回收它们占据的内存。

(14)对象的强,软,弱,虚引用。

强引用:如果一个对象具有强引用,垃圾回收器绝不会回收它。当内存空间不足,JVM宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会考随意回收具有强引用的对象来解决内存不足的问题。

软引用:如果一个对象具有软引用。如果内存空间足够。垃圾回收器不会回收它。如果内存不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

弱引用:如果一个对象具有弱引用。当垃圾回收器发现只具有弱引用对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现只具有弱引用的对象。

虚引用:虚引用不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/2283.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法…

    台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法…有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始”菜单或者左下角的windows标志处,找到“控制面板”然后找到”windowsupdate”把这微软默认的更新程序给关闭掉,可解决!(经测试,此方法能解决大多数这种问题)如果解决…

    2022年6月15日
    159
  • Django(15)外键和表关系[通俗易懂]

    Django(15)外键和表关系[通俗易懂]外键删除操作如果一个模型使用了外键。那么在对方那个模型被删掉后,该进行什么样的操作。可以通过on_delete来指定。可以指定的类型如下:CASCADE:级联操作。如果外键对应的那条数据被删除了,

    2022年7月28日
    4
  • 怎么把sql删干净_sql的导入和导出的好处

    怎么把sql删干净_sql的导入和导出的好处程序数据库(PDB)文件保存着调试和项目状态信息,使用这些信息可以对程序的调试配置进行增量链接。在使用/debug生成时,会创建一个PDB文件。可以使用/debug:full或/debug:pdbonly生成应用程序。使用/debug:full生成将产生可调试的代码。使用/debug:pdbonly生成将产生PDB,但是不会产生通知JIT编译器调试信息可用…

    2022年9月25日
    4
  • RCU 机制_NRPS作用机制

    RCU 机制_NRPS作用机制《RCU是什么?》第一部分概述Read-copyupdate(RCU)是一种2002年10月被引入到内核当中的同步机制。通过允许在更新的同时读数据,RCU提高了同步机制的可伸缩性(scalability)。相对于传统的在并发线程间不区分是读者还是写者的简单互斥性锁机制,或者是哪些允许并发读但同时不允许写的读写锁,RCU支持同时一个更新线程和多个读线程的并发。R…

    2025年5月26日
    4
  • 【转载】Socket通讯原理以及TCP、IP三次握手机制分析

    【转载】Socket通讯原理以及TCP、IP三次握手机制分析

    2021年11月18日
    40
  • 数据同步利器-otter的搭建使用说明「建议收藏」

    数据同步利器-otter的搭建使用说明「建议收藏」一、Otter目前支持了什么1.单向同步,mysql/oracle互相同步2.双向同步,无冲突变更3.文件同步,本地/aranda文件4.双A同步,冲突检测&冲突补救5.数据迁移,中间表/行记录同步导历史表还需要程序实现吗?还在用mysql的主从复制吗?Otter都能为你解决。典型的场景

    2022年6月8日
    96

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号