本文经授权转载自程序员杂货铺(ID;speakFramework)

垃圾回收

最近上海的小伙伴是不是要被强垃圾分类搞疯了???哈哈哈哈
上海是个走在前列的城市啊,不光骑自行车闯红灯要被罚钱,垃圾不分类扔了还要被罚钱。法制!是个好事。
今天我们也了解一下面试中必问的问题:java垃圾回收机制

垃圾回收机制是由垃圾收集器Garbage Collection GC来实现的,GC是后台的守护进程
它的特别之处在于它是一个低优先级进程,但是可以根据内存的使用情况动态的调整他的优先级。因此,它是在内存中低到一定限度时才会自动运行,从而实现对内存的回收。这就是垃圾回收的时间不确定的原因。
(这样设计的原因:GC也是一进程,需要消耗CPU的资源,频繁的GC势必会对程序造成影响)

在程序运行期间,所有的对象实例都存储在运行时数据区的中(heap),当一个对象不再使用,需要被回收时候,GC调用回收的方法:gabage collector方法。在此过程中GC会对java对象的生命周期等做分析,会用分代(后续细说)的方式对java对象进行回收,尽可能避免GC造成程序暂停的影响

垃圾回收之前的准备工作:
因为垃圾回收只能回收通过New关键字在堆(heap)上申请的内存,但是堆中的内存并不全都是通过new创建的,还有一部分本地方方法(一般是C的方法),GC是无法回收这一部分的内存的,需要手动去释放,所以需要在finalize中用本地方法(native method)如free操作等,再使用gc方法。显示的GC方法是system.gc()

关于对象的引用

在jdk1.2之前,java对引用的定义:如果reference类型的数据中存储的数值代表的是另一块内存的其实地址,那么称这块内存代表着一个引用。

这样的定义,有些狭隘,如此一来,一个对象只有被引用和没有被引用两种状态,实际中有些对象是一种“食之无味,弃之可惜”的的状态存在,也就是说,有没有都可以。我们希望这一类对象也能被描述:内存足够时就存在,内存不够时就抛弃。很多系统的缓存功能就是这么存在的。

在jdk1.2之后对象的引用被分为:强引用,软引用,弱引用,虚引用4中强度递减
java对象引用类型:

  1. 强引用(Strong Reference):代码中普遍存在,类似于“Object obj = new Object()”引用,只要引用存在就不会被回收

  2. 软引用(Soft Reference):描述可能有用但非必须的对象,在系统僬侥发生内存溢出异常时,会把这些对象纳入回收范围内进行回收,如果内存还不够的话,就会抛出内存溢出异常。

  3. 弱引用(Weak Reference):描述非必须对象的,被弱引用关联的对象一定会被回收,只能存活到下次垃圾收集之前

  4. 虚引用(Phantom Reference):最弱的一种引用关系,又称幽灵引用或者幻影引用。一个对象是否有虚引用的存在,不会对其生存时间造成影响,也无法通过虚引用得到一个对象。为一个对象设置虚引用关联的唯一目的是希望能在这个对象被收集器回收时收到一个系统通知

何为垃圾

简而言之:没有办法再引用的对象,视为垃圾

1、引用计数法:
给对象添加一个引用计数器,每当有地方引用它,计数器+1;引用失效,计数器-1;当计数器为0的对象就是不可再调用的对象
这种方式,简单粗暴,高效,但是现在主流虚拟机中并没有使用它来判断对象是否是垃圾,主要原因在于:它很难解决对象与对象之间互相循环引用的问题

2、根搜索算法(可达性分析算法):
根集(Root Set):就是正在执行的java程序可以访问的引用变量的集合(不是对象的集合),程序可以使用引用变量访问它的属性和方法
根搜索算法就是通过一系列的GC Roots的对象作为起点,一直向下寻找对应的引用节点,所经过的路径称为引用链,当一个对象到GC Roots没有任何引用链时,可视为此对象是垃圾(java和C#都使用根搜索算法来判断对象存活的)

在java中,可作为GC Roots的对象包括:

  1. 虚拟机栈(栈帧中的局部变量表)中引用的对象

  2. 方法区中静态属性引用的对象

  3. 方法区中常量引用的对象

  4. 本地方法(native)引用的对象

需要注意的是:在可达性法系算法中不可达的对象,也不一定是“非死不可”的,这只是一审,还会有一次二审。也就是说,真正的宣判“死亡”要经理两次标记:
在可达性分析算法之后如果没有可达路径,它将被第一次标记为“垃圾”并进行一次筛选,筛选的条件是:此对象是否有必要执行finalize()方法
当对象没有覆盖finalize()或者finalize()已经被虚拟机调用过。虚拟机将这两种情况都视为“没有必要执行”

如果当前对象被判定没有必要去执行finalize()方法时,这个对象将会被放到F-Queue的队列中,并在稍后又虚拟机自己去建立一个Finalizer线程去执行它。(这里的执行指的是触发它,而补水去等待他的结果,避免该过程死锁)

在此期间,对象还是有机会“逃生”的,方法就是:重新与引用链上的对象建立关联即可

GC会对F-Queue里面的对象进行二次标记,二次标记之后也会被移出F-Queue,这时候该对象就被“二审宣判”了。

需要回收方法区吗?
java虚拟机规范中确实说过不要求虚拟机在方法区实现垃圾回收,而且,即使回收,性价比也是很低的,不值得。

怎么回收

垃圾收集的算法:
1、标记-清除算法(Tracing算法):
标记阶段:标记出所有需要被回收的对象
清除阶段:回收被标记对象的内存空间

(图片来源于网络)

优点:不需要对对象移动,不需要对存活的对象进行操作,在存活对象较多的情况下效率非常高
缺点:①标记和清除的过程效率都不高(需要闲置的列表来记录空闲区域的大小,此过程会增加分配对象的工作量)。②标记清除后会产生大量的不连续的碎片,这样导致的结果是回收完一次,虽然有一部分空闲的空间,但是没有一个单一的区域来满足本次分配,可以说是失败的,可能还需触发一次垃圾回收

2、复制算法(Copying算法):
为了解决标记-清除算法的缺点,它将堆栈分为两个区域,按容量划分成大小相等的两块,也称半空间,每次只使用其中的一块(对象面),当着一块用完了就将还存活着的对象复制到另外一块(空闲面),再把已使用的内存空间清理掉,这样一来就不会出现内存碎片的问题了

(图片来源于网络)

优点:标记和复制阶段可以同时运行;算法实现简单,运行高效且不容易产生内存碎片
缺点:对内存空间的使用做出了高昂的代价,因为能够使用的内存缩减到原来的一半,不适用于存活对象多的情况

ps:复制算法比较适合新生代对象(短期存活),因为在老年代中存活率比较高,不适合复制算法

3、标记-整理算法(Compacting算法):

标记:标记出所有需要被回收的对象
整理:不直接对可回收对象进行回收,而是将所有的对象都向一端移动,然后直接清理掉边界以外的内存

(图片来源于网络)

优点:①整理后新对象的分配只需要通过指针碰撞便能完成(Pointer Bumping),相当简单;②标记整理算法使得空闲区域的位置是始终可知的,也不会再有碎片的问题了。
缺点:GC暂停的时间会增长,因为你需要将所有的对象都拷贝到一个新的地方,还得更新它们的引用地址。

4、分代收集算法(Generational Collection)

分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干块区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation)

  • 老年代:对象的存活率高,每次垃圾收集时只有少量对象需要被回收,没有多余的空间进行整理,所以使用“标记-清除”或者“标记-整理”算法来进行回收

  • 新生代:采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,存活的很少,也就是说需要复制的操作次数较少

注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。

垃圾回收的意义

java语言显著的特点就是引入了java回收机制,是c++程序员最头疼的内存管理的问题迎刃而解,这样一来,我们在开发的过程中就不必考虑内存管理。垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。

☞  为啥程序员下班后只关显示器从不关电脑?

☞  女朋友生气了吗?算法比直男更懂她

☞  迁徙在互联网风口之间的年轻人

你点的每个“在看”,我都认真当成了喜欢

java垃圾回收机制_笔记 | Java垃圾回收机制相关推荐

  1. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  2. 6种java垃圾回收算法_学习java垃圾回收

    垃圾回收(GC)一直是Java受欢迎背后的重要特性之一.垃圾回收是Java中用于释放未使用的内存的机制.本质上,它追踪所有仍在使用的对象,并将剩下的标记为垃圾.Java的垃圾回收被认为是一种自动内存管 ...

  3. jvm垃圾回收机制_干货|JVM垃圾回收机制

    前言 不同于C++程序员必须自己完成内存的分配.使用和释放,JAVA语言提供了垃圾回收机制(GC,Garbage Collection),所以JAVA程序员仅需要负责分配和使用内存即可,而释放内存则由 ...

  4. python垃圾回收价格表_主流的垃圾回收机制都有哪些?

    常用的垃圾收集算法 目录如下:引用计数法 标记-清除算法(Mark-Sweep) 复制算法(Copying) 标记-整理算法(Mark-compact) 分代收集算法 Generational Col ...

  5. python垃圾回收离职_谈谈python垃圾回收机制

    什么是垃圾回收机制? 首先,咱先来解释名词,垃圾回收是不是就是将没用的,废弃的东西回收起来. 在坐的各位都没有女朋友对吧,那难以想象你们的房间会是一个什么样子,可能会有很多垃圾,很凌乱,自己也不收拾. ...

  6. java提供两种处理异常的机制_浅析Java异常处理机制

    关于异常处理的文章已有相当的篇幅,本文简单总结了Java的异常处理机制,并结合代码分析了一些异常处理的最佳实践,对异常的性能开销进行了简单分析. 博客另一篇文章<[译]Java异常处理的最佳实践 ...

  7. 类加载器 java委托机制_解析Java虚拟机中类的初始化及加载器的父委托机制

    类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始化: 2.在静态代码块中进行初始化. 没有 ...

  8. java 反射创建属性_使用Java反射机制确定基本数据类型属性

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 Java反射机制提供了一种强大的应用程序接口来帮助我们在运行时检测和执行对象上的操作.该机制允许程序员审视一个未知对象,并且获得它的属性,例如对象上的方法 ...

  9. JAVA redis缓存过期_失效java服务器

    Java 并发/多线程教程--4并发模型 本系列译自jakob jenkov的Java并发多线程教程(本章节部分内容参考http://ifeve.com/并发编程模型),个人觉得很有收获.由于个人水平 ...

最新文章

  1. swift_009(Swift 类型别名/安全/推断)
  2. 第一章:最小可行区块链
  3. docker 之 Dockerfile 实践
  4. 5月25号GE一面经历
  5. blender使用_DigiVita使用Blender教女孩编码
  6. 如何区分广播风暴和网络环路?
  7. 为什么Android项目mainactivity中有一个变量R_安卓4:第一个安卓程序 AS 安卓项目结构解析 手机运行app 模拟器运行app...
  8. discuz mysql配置文件_MySQL优化配置文件my.ini(discuz论坛)
  9. 黑暗森林:知识图谱的前世今生
  10. 典型的php系统由什么组成,完整的计算机系统由什么组成
  11. excel表格乱码怎么解决呢?
  12. CDR X4无法使用怎么解决
  13. Android——8种通知栏-适配 Adnroid12
  14. 信息系统项目管理师 - 项目沟通管理
  15. 验证iOS应用的无障碍特性
  16. 数据结构与算法——先导篇
  17. linux命令返回结果保存到文件,Linux终端运行命令及结果同时保存入文件方法总结...
  18. 生信学习——基于R的可视化习题30个(附详细答案解读)
  19. 漫话:如何给女朋友解释为什么日本时间比中国时间快一个小时
  20. 产品项目团队都有哪些角色概览

热门文章

  1. 概率潜在语义分析(Probabilistic Latent Semantic Analysis,PLSA)
  2. python和R对dataframe进行连接、行过滤更新列内容:dplyr、merge、inner、left、right、inner_join、left_join、sort_values、loc
  3. 新版IntelliJ IDEA Web项目配置完整流程
  4. R语言之斐波那契数列
  5. laravel php跨域请求,laravel开发中跨域的解决方案
  6. JAVA基础10-继承(1)
  7. flask项目中无法更改端口号
  8. python 在无网络环境下安装包
  9. CNN网络加速--Performance Guaranteed Network Acceleration via High-Order Residual Quantization
  10. linux主机设置本地swap