首页 > 其他分享 >垃圾回收机制

垃圾回收机制

时间:2023-12-25 19:44:07浏览次数:34  
标签:标记 对象 内存 回收 算法 垃圾 机制 引用

一般说来,我们要解决三个问题: 1、回收哪些内存? 2、什么时候回收? 3、如何回收?    首先我们来看Java的四种引用类型:   强引用:代码中普遍存在的,只要强引用还存在,垃圾收集器就不会回收掉被引用的对象。   软引用:SoftReference,软引用是介于强引用和弱引用之间的引用类型。当系统内存不足时,垃圾回收器会尝试回收只有软引用指向的对象。与弱引用不同的是,软引用通常会在内存不足时才被回收,因此适合用于实现内存敏感的缓存。   弱引用:WeakReference,当一个对象只有弱引用指向时,垃圾回收器在下一次垃圾回收时可能会回收该对象。弱引用通常用于实现缓存或者容器类,允许对象在没有强引用时被自动回收。   虚引用:PhantomReference,一个对象是否有虚引用的存在,完全不会对其生存时间产生影响,也无法通过虚引用取得一个对象的引用,它存在的唯一目的是在这个对象被回收时可以收到一个系统通知。     不同的引用类型,在做 GC 时会区别对待,我们平时生成的 Java 对象,默认都是强引用,也就是说只要强引用还在,GC 就不会回收,那么如何判断强引用是否存在呢?   一个简单的思路就是:引用计数法,有对这个对象的引用就+1,不再引用就-1,但是这种方式看起来简单美好,但它却不能解决循环引用计数的问题。因此可达性分析算法登上历史舞台,用它来判断对象的引用是否存在。   可达性分析算法: 通过一系列称为 GCRoots 的对象作为起始点,从这些节点从上向下搜索,所走过的路径称为引用链,当一个对象没有任何引用链与 GCRoots连接时就说明此对象不可用,也就是对象不可达。   GC Roots 对象通常包括:   1、虚拟机栈中引用的对象(栈帧中的本地变量表)   2、方法区:类的静态属性对象   3、方法区:常量引用的对象   4、本地方法栈JNI(Native 方法)中的对象

 

 

 

 例子一:

 

 GCRoot1由于是静态变量,所以它属于GCRoot对象。在方法还没执行完之前,这五个变量都是属于GCRoot组的,此时GC无法回收。

但是如果方法执行完成后,本地变量表中的对象:object1,object2,object3,object4,都会从GCRoot组里面移除出来。

 

 

 

 

 变为:

  

由于引用链的存在,所以在GCRoot1没有被回收之前,下面四个局部变量(本应该被回收的)都不会被回收。

 

例子二:

 

 

 

在方法还没完成前,object5,object6,object7都属于本地变量表,所以都在GCRoot组里面。

方法完成后:

 

 

object5,object6,object7都会被移除GCRoot,这时候GC扫描的时候,由于引用链向上找不到GCRoot对象,所以object5,object6,object7都会被释放,o的话根据自己的生命周期决定是否释放。

 

 如何减少OOM的概率:

1、尽可能少的发生内存泄漏。

2、尽可能不在循环中申请内存。

3、尽可能不在调用次数多的函数中申请内存。

 

 

可达性分析算法整个流程如下所示: 第一次标记:对象在经过可达性分析后发现没有与 GC Roots 有引用链,则进行第一次标记并进行一次筛选,筛选条件是:该对象是否有必要执行 finalize()方法。没有覆盖 finalize()方法或者 finalize()方法已经被执行过都会被认为没有必要执行。 如果有必要执行:则该对象会被放在一个 F-Queue 队列,并稍后在由虚拟机建立的低优先级 Finalizer 线程中触发该对象的 finalize()方法,但不保证一定等待它执行结束,因为如果这个对象的 finalize()方法发生了死循环或者执行时间较长的情况,会阻塞 F-Queue 队列里的其他对象,影响 GC。   第二次标记:GC 对 F-Queue 队列里的对象进行第二次标记,如果在第二次标记时该对象又成功被引用,则会被移除即将回收的集合,否则会被回收。 总之,JVM 在做垃圾回收的时候,会检查堆中的所有对象否会被这些根集对象引用,不能够被引用的对象就会被圾收集器回收。   一般回收算法也有如下几种: 1).标记-清除(Mark-sweep) 标记-清除算法采用从根集合进行扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收。标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片。   2).标记-整理(Mark-Compact) 标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针。标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题。该垃圾回收算法适用于对象存活率高的场景(老年代)。   3).复制(Copying) 复制算法将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这种算法适用于对象存活率低的场景,比如新生代。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况。   4).分代收集算法 不同的对象的生命周期(存活情况)是不一样的,而不同生命周期的对象位于堆中不同的区域,因此对堆内存不同区域采用不同的策略进行回收可以提高 JVM 的执行效率。当代商用虚拟机使用的都是分代收集算法:新生代对象存活率低,就采用复制算法;老年代存活率高,就用标记清除算法或者标记整理算法。Java堆内存一般可以分为新生代、老年代和永久代三个模块

 

标签:标记,对象,内存,回收,算法,垃圾,机制,引用
From: https://www.cnblogs.com/tangZH/p/15113823.html

相关文章

  • 云服务器比传统服务器更安全的原因与实现机制
    本文分享自天翼云开发者社区《云服务器比传统服务器更安全的原因与实现机制》,作者:3****m随着互联网的普及和云计算技术的发展,越来越多的企业和组织选择使用云服务器来提供和存储数据。与传统服务器相比,云服务器在安全性方面具有诸多优势。本文将围绕云服务器比传统服务器更安全的......
  • 如何在Go语言中处理反爬虫机制
    在当今互联网时代,网站的反爬虫机制变得越来越普遍。这些机制旨在保护网站的数据和资源,防止恶意爬虫对网站造成过大负荷。对于Go语言开发者来说,了解如何处理反爬虫机制是至关重要的。本文将介绍一些在Go语言中处理反爬虫机制的方法和技巧。1.使用合适的User-AgentUser-Agent是HTTP请......
  • cgo 机制
    Go语言是通过自带的一个叫CGO的工具来支持C语言函数调用,同时我们可以用Go语言导出C动态库接口给其它语言使用。基于C标准库实现最简单的CGO程序//hello.gopackagemain//#include<stdio.h>import"C"funcmain(){C.puts(C.CString("Hello,thisisaCGOdem......
  • jdk和dubbo的SPI机制
    jdk和dubbo的SPI机制转载自:https://www.cnblogs.com/wyq178/p/12171881.html前言:开闭原则一直是软件开发领域中所追求的,开闭原则中的"开"是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的,“闭”,是指对于原有代码的修改是封闭的,即不应该修改原有的代码。对......
  • c++智能指针和java垃圾回收对比
    c++智能指针和java垃圾回收对比我们都知道C++和java语言的一个巨大差异在于垃圾回收方面,这也是C++程序开发者和java程序开发者之间经常讨论的一个话题。在C++语言中,一般栈上的内存随着函数的生命周期自动进行回收,但是堆上内存(也就是自己new/malloc出来的空间),需要自己手动进行del......
  • 观察者模式揭秘:实现松耦合的事件通知机制
    推荐语本篇文章深度剖析了观察者模式的核心原理及其在软件开发中的重要应用,通过清晰而深入的讲解,读者小伙伴可以深入理解观察者模式如何实现松耦合的事件通知机制,从而构建更灵活、可扩展的软件系统。本文既适合希望深入了解设计模式的专业人士,也适合希望提升代码质量和可维护性的开......
  • linux修改内核参数禁止OOM机制
    Linux内核有个机制叫OOMkiller(Out-Of-Memorykiller),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽,内核会把该进程杀掉,监控是正常的。防止重要的系统进程触发(OOM)机制而被杀死:可以设置参数/proc/PID/oom_adj为-17,临时关闭linux内核的OOM机制......
  • Eureka Server 自我保护机制
    https://blog.csdn.net/u012410733/article/details/112303048下面是官方提供的Eureka架构图: 1、什么是自我保护机制默认情况下,如果EurekaServer在一定时间内(默认90秒,其实不止90秒)没有接收到某个微服务实例的心跳,EurekaServer将会移除该实例。但是当网络分区故障发生......
  • centos6和7的模板机制作
    centos6(安装操作系统直接最小化安装就行)1.进入网卡配置文件将网卡的MAC和UUID删除(网卡需要开机自启的话,只要把ONBOOT=no改为ONBOOT=yes就行)2.挂在光盘,临时挂在3.制作yum源yumcleanall#清楚yum源的缓存yummakecache#生成新的yum源yum -y install g......
  • 2-2自动微分机制
    0.配置神经网络通常依赖反向传播求梯度来更新网络参数,求梯度过程通常是一件非常复杂而容易出错的事情。而深度学习框架可以帮助我们自动地完成这种求梯度的运算。Pytorch一般通过反向传播backward方法实现这种求梯度计算。该方法求得的梯度将存在对应自变量张量的grad属性下......