一篇文章搞定java中的垃圾回收机制面试题

 
  1. 任何语言在运行过程中都会创建对象,也就意味着需要在内存中为这些对象在内存中分配空间,在这些对象失去使用的意义的时候,需要释放掉这些内容,保证内存能够提供给新的对象使用。对于对象内存的释放就是垃圾回收机制,也叫做gc,对于java开发者来说gc是一个双刃剑

  2. 我们这里找了两张搞笑图片分别来表示c语言的垃圾回收和 java的垃圾回收。

  3. 注意:并不是说谁好谁坏,只是一个调侃图。

我们这里找了两张搞笑图片分别来表示c语言的垃圾回收和 java的垃圾回收。 注意:并不是说谁好谁坏,只是一个调侃图。

c语言:

java语言:

 
  1. c的垃圾回收是人工的,工作量大,但是可控性高。

  2. java是自动化的,但是可控性很差,甚至有时会出现内存溢出的情况,

  3. 内存溢出也就是jvm分配的内存中对象过多,超出了最大可分配内存的大小。

c的垃圾回收是人工的,工作量大,但是可控性高。 java是自动化的,但是可控性很差,甚至有时会出现内存溢出的情况, 内存溢出也就是jvm分配的内存中对象过多,超出了最大可分配内存的大小。

 
  1. 提到java的垃圾回收机制就不得不提一个方法:

  2.  System.gc()用于调用垃圾收集器,在调用时,垃圾收集器将运行以回收未使用的内存空间。它将尝试释放被丢弃对象占用的内存。

  3.  然而System.gc()调用附带一个免责声明,无法保证对垃圾收集器的调用。

  4.  所以System.gc()并不能说是完美主动进行了垃圾回收。

​  System.gc()用于调用垃圾收集器,在调用时,垃圾收集器将运行以回收未使用的内存空间。它将尝试释放被丢弃对象占用的内存。  然而System.gc()调用附带一个免责声明,无法保证对垃圾收集器的调用。  所以System.gc()并不能说是完美主动进行了垃圾回收。

 
  1.  作为java程序员还是很有必要了解一下gc,这也是面试过程中经常出现的一道题目。

  2.  我们从三个角度来理解gc。

  3.  1jvm怎么确定哪些对象应该进行回收

  4.  2jvm会在什么时候进行垃圾回收的动作

  5.  3jvm到底是怎么清楚垃圾对象的

 作为java程序员还是很有必要了解一下gc,这也是面试过程中经常出现的一道题目。  我们从三个角度来理解gc。  1jvm怎么确定哪些对象应该进行回收  2jvm会在什么时候进行垃圾回收的动作  3jvm到底是怎么清楚垃圾对象的  

jvm怎么确定哪些对象应该进行回收

 
  1.  对象是否会被回收的两个经典算法:引用计数法,和可达性分析算法。

 对象是否会被回收的两个经典算法:引用计数法,和可达性分析算法。

引用计数法

 
  1.  简单的来说就是判断对象的引用数量。实现方式:给对象共添加一个引用计数器,每当有引用对他进行引用时,计数器的值就加1,当引用失效,也就是不在执行此对象是,他的计数器的值就减1,若某一个对象的计数器的值为0,那么表示这个对象没有人对他进行引用,也就是意味着是一个失效的垃圾对象,就会被gc进行回收。

  2.  但是这种简单的算法在当前的jvm中并没有采用,原因是他并不能解决对象之间循环引用的问题。

  3.  假设有A和B两个对象之间互相引用,也就是说A对象中的一个属性是B,B中的一个属性时A,这种情况下由于他们的相互引用,从而是垃圾回收机制无法识别。

 简单的来说就是判断对象的引用数量。实现方式:给对象共添加一个引用计数器,每当有引用对他进行引用时,计数器的值就加1,当引用失效,也就是不在执行此对象是,他的计数器的值就减1,若某一个对象的计数器的值为0,那么表示这个对象没有人对他进行引用,也就是意味着是一个失效的垃圾对象,就会被gc进行回收。  但是这种简单的算法在当前的jvm中并没有采用,原因是他并不能解决对象之间循环引用的问题。  假设有A和B两个对象之间互相引用,也就是说A对象中的一个属性是B,B中的一个属性时A,这种情况下由于他们的相互引用,从而是垃圾回收机制无法识别。

 

 
  1.  因为引用计数法的缺点有引入了可达性分析算法,通过判断对象的引用链是否可达来决定对象是否可以被回收。可达性分析算法是从离散数学中的图论引入的,程序把所有的引用关系看作一张图,通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连(就是从 GC Roots 到这个对象不可达)时,则证明此对象是不可用的。

 因为引用计数法的缺点有引入了可达性分析算法,通过判断对象的引用链是否可达来决定对象是否可以被回收。可达性分析算法是从离散数学中的图论引入的,程序把所有的引用关系看作一张图,通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连(就是从 GC Roots 到这个对象不可达)时,则证明此对象是不可用的。

 如图:

二在确定了哪些对象可以被回收之后,jvm会在什么时候进行回收

 
  1.  1会在cpu空闲的时候自动进行回收

  2.  2在堆内存存储满了之后

  3.  3主动调用System.gc()后尝试进行回收

 1会在cpu空闲的时候自动进行回收  2在堆内存存储满了之后  3主动调用System.gc()后尝试进行回收

三如何回收

 
  1. 三如何回收

  2.  如何回收说的也就是垃圾收集的算法。

  3.  算法又有四个:标记-清除算法,复制算法,标记-整理算法,分代收集算法.

  4.  

  5.  1 标记-清除算法。

  6.  这是最基础的一种算法,分为两个步骤,第一个步骤就是标记,也就是标记处所有需要回收的对象,标记完成后就进行统一的回收掉哪些带有标记的对象。这种算法优点是简单,缺点是效率问题,还有一个最大的缺点是空间问题,标记清除之后会产生大量不连续的内存碎片,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而造成内存空间浪费。

三如何回收  如何回收说的也就是垃圾收集的算法。  算法又有四个:标记-清除算法,复制算法,标记-整理算法,分代收集算法.    1 标记-清除算法。  这是最基础的一种算法,分为两个步骤,第一个步骤就是标记,也就是标记处所有需要回收的对象,标记完成后就进行统一的回收掉哪些带有标记的对象。这种算法优点是简单,缺点是效率问题,还有一个最大的缺点是空间问题,标记清除之后会产生大量不连续的内存碎片,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而造成内存空间浪费。

执行如图:

 
  1. 2复制算法。

  2. 复制将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况。只是这种算法的代价是将内存缩小为原来的一半。

2复制算法。 复制将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况。只是这种算法的代价是将内存缩小为原来的一半。

复制算法的执行过程如图:复制收集算法在对象存活率较高时就要执行较多的复制操作,效率将会变低。更关键的是,浪费了一半的空间。

 
  1. 标记-整理算法:

  2. 标记整理算法与标记清除算法很相似,但最显著的区别是:标记清除算法仅对不存活的对象进行处理,剩余存活对象不做任何处理,造成内存碎片;而标记整理算法不仅对不存活对象进行处理清除,还对剩余的存活对象进行整理,重新整理,因此其不会产生内存碎片。

标记-整理算法: 标记整理算法与标记清除算法很相似,但最显著的区别是:标记清除算法仅对不存活的对象进行处理,剩余存活对象不做任何处理,造成内存碎片;而标记整理算法不仅对不存活对象进行处理清除,还对剩余的存活对象进行整理,重新整理,因此其不会产生内存碎片。

标记整理算法的作用示意图如下: 

 
  1. 分代收集算法:

  2. 分代收集算法是一种比较智能的算法,也是现在jvm使用最多的一种算法,他本身其实不是一个新的算法,而是他会在具体的场景自动选择以上三种算法进行垃圾对象回收。

分代收集算法: 分代收集算法是一种比较智能的算法,也是现在jvm使用最多的一种算法,他本身其实不是一个新的算法,而是他会在具体的场景自动选择以上三种算法进行垃圾对象回收。

 
  1. 那么现在的重点就是分代收集算法中说的自动根据具体场景进行选择。这个具体场景到底是什么场景。

  2. 场景其实指的是针对jvm的哪一个区域,1.7之前jvm把内存分为三个区域:新生代,老年代,永久代。

那么现在的重点就是分代收集算法中说的自动根据具体场景进行选择。这个具体场景到底是什么场景。 场景其实指的是针对jvm的哪一个区域,1.7之前jvm把内存分为三个区域:新生代,老年代,永久代。

 
  1. 了解过场景之后再结合分代收集算法得出结论:

  2. 1、在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法。只需要付出少量存活对象的复制成本就可以完成收集。

  3. 2、老年代中因为对象存活率高、没有额外空间对他进行分配担保,就必须用标记-清除或者标记-整理。

了解过场景之后再结合分代收集算法得出结论: 1、在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法。只需要付出少量存活对象的复制成本就可以完成收集。 2、老年代中因为对象存活率高、没有额外空间对他进行分配担保,就必须用标记-清除或者标记-整理。

总结:

 
  1. 注意:

  2. 在jdk8的时候java废弃了永久代,但是并不意味着我们以上的结论失效,因为java提供了与永久代类似的叫做“元空间”的技术。

  3. 废弃永久代的原因:由于永久代内存经常不够用或发生内存泄露,爆出异常java.lang.OutOfMemoryErroy。元空间的本质和永久代类似。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。也就是不局限与jvm可以使用系统的内存。理论上取决于32位/64位系统可虚拟的内存大小。

注意: 在jdk8的时候java废弃了永久代,但是并不意味着我们以上的结论失效,因为java提供了与永久代类似的叫做“元空间”的技术。 废弃永久代的原因:由于永久代内存经常不够用或发生内存泄露,爆出异常java.lang.OutOfMemoryErroy。元空间的本质和永久代类似。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。也就是不局限与jvm可以使用系统的内存。理论上取决于32位/64位系统可虚拟的内存大小。

一篇文章搞定java中的垃圾回收机制面试题相关推荐

  1. JAVA中的垃圾回收机制以及其在android开发中的作用

    http://blog.csdn.net/xieqibao/article/details/6707519 这篇文章概述了JAVA中运行时数据的结构,以及垃圾回收机制的作用.在后半部分,描述了如何检测 ...

  2. [转载] Python和java中的垃圾回收机制

    参考链接: Python中的垃圾回收 Python的垃圾回收机制 Python的垃圾回收机制有两种(也可以说一种:叫引用计数): 一是引用计数, 二是隔代回收. 引用计数 引用计数原理: 当数据的引用 ...

  3. 一篇文章搞定java序列化机制

    序列化与反序列化 序列化:将对象的状态信息转换为可以存储或传输的数据形式(比如二进制)的过程. 反序列化:与序列化相对,把序列化转换成的可以存储或传输的数据形式转化为对象的状态信息的过程. java序 ...

  4. 一篇文章搞清楚Java中CompletableFuture的使用

    ---------- Yesterday is history, tomorrow is a mystery, but today is a gift. That is why it's called ...

  5. 第八章软件构造的性能——构造性能的度量、原则与方法(java中的垃圾回收机制及算法)

    这节内容真的是多到炸裂,而且全都是概念,不过很挺有用的,学完这节会对内存管理有一个比较深的理解和认识,就是--这也太多了--嘤嘤嘤T_T 1.性能度量(performance metrics) 第一点 ...

  6. 《对Java的分析总结》-Java中的垃圾回收机制中的标记-清除算法 (五)

    标记-清除算法 标记-清除算法(mark-sweep 1 标记-清除算法 回收过程描述 类别 描述 mutator 设置 collector 收集 mutator roots mutator根对象 1 ...

  7. 一篇文章搞定面试中的二叉树题目(java实现)

    转载:http://www.jianshu.com/p/0190985635eb 最近总结了一些数据结构和算法相关的题目,这是第一篇文章,关于二叉树的. 先上二叉树的数据结构: class TreeN ...

  8. 一篇文章搞定Java处理Excel表格的各种疑难杂症

    文章目录 简介 结构 Maven Gradle 扩展组件知识 快速体验 创建Excel 读取Excel 开发指南 读取Excel方法对比 读取Excel的所有Sheet 方式一 方式二 读取单元格的值 ...

  9. 一篇文章搞定面试中的二叉树

    转载自  IOExceptioner  算法与数据结构 在上一篇介绍二叉树( Android面试题算法之二叉树 .红黑树详细分析,看了都说好),没看的读者建议先去了解了解,接下来再给大家带来一篇关于二 ...

最新文章

  1. 多线程编程 - GCD
  2. python 循环添加array_Python的备忘细节小抄
  3. linux查看某端口进程占用,Linux下查看某端口占用进程
  4. 命令 / Linux / netstat 详解
  5. aws terraform_如何使用Terraform通过Direct Connect扩展AWS基础架构
  6. FireMonkey 源码学习(2)
  7. i计算机网络的应用程序,计算机网络技术及其在校园网的研究与应用毕业论文.doc...
  8. python装饰器快速入门
  9. 连接动态链接库时找不到链接库的解决办法
  10. UKEY开发 用户登录流程
  11. EPICS Archiver Appliance在Debian11下安装文档
  12. 拆弹实验-phase_5
  13. 亚马逊账号关联的后果是什么
  14. 苹果iPad怎么录屏?简单易懂,1分钟学会
  15. 如何设置Ubuntu 自动待机时间
  16. 在 CloudIDE 里实现天猫精灵自定义技能的业务逻辑
  17. 使用python脚本批量修改vc工程文件
  18. 从零开始写一个小米便签
  19. 在项目中CR是什么意思?
  20. 关于微信小程序获取头像和昵称

热门文章

  1. python函数画圆_python圆形_python圆形绘制_python圆形函数 - 云+社区 - 腾讯云
  2. 网络层ICMP和ARP协议介绍
  3. 压缩解压函数实现(转)
  4. Trafodion CQD控制查询执行
  5. Profinet工业以太网超高频RFID读写器|读卡器CK-UR12-E02的RFID标签地址分配与操作流程
  6. 快过年了,搞笑开启过年模式
  7. 马凯军 周强 张季跃《面向对象与程序设计 Java》第十四周学习总结
  8. 《啊哈!算法》知识点汇总
  9. 【推荐收藏】11种比较常用的时间序列预测模型
  10. 微信小程序商城项目实战(第一篇:项目搭建与首页)