垃圾回收GC详解——《深入理解Java虚拟机》读书笔记

上一篇:HotSpot虚拟机对象——《深入理解java虚拟机》读书笔记

1、java程序员为什么要去了解垃圾收集和内存分配?
答:当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就必须对这些”自动化“的技术实施必要的监控和调节——3.1概述
2、哪些需要垃圾回收?
答:前面的文章已经介绍了java虚拟机运行时数据区主要分为两大部分:程序计数器、java虚拟机栈和本地方法栈为线程隔离的数据区;java堆和方法区为所有线程共享的数据区。其中前者依赖用户线程的启动和结束而建立和销毁,因此不需要过多考虑如何回收的问题。后者则有着显著的不确定性,这部分内存的分配和回收是动态的。垃圾收集器所关注的正是这部分内存该如何管理——3.1概述
3、判断对象是否存活的算法有哪些?
答:《深入理解java虚拟机》书中介绍了两种:引用计数算法和可达性分析算法。
引用计数算法:在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计算器值就减一;任何时刻计数器为零的对象就是不可能再被使用的——3.2.1
缺点:看似简单但有很多例外情况要考虑,必须配合大量额外处理才能保证正确工作,譬如单纯的引用计数就很难解决对象之间相互循环引用的问题。
可达性分析算法:基本思路是通过一系列称为"GC Roots"的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”,如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。——3.2.2
4、JDK1.2之后Java的引用类型有哪些?
答:强引用、软引用、弱引用、虚引用,引用强度一次逐渐减弱。
强引用是最传统的“引用定义”。指在程序代码之中普遍存在的引用赋值,类似“Object obj = new Object()”
软引用是用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,只会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够内存,才会抛出内存溢出异常。JDK1.2版本之后提供了SoftReference类来实现软引用。
弱引用也是用来描述那些非必须对象,但它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。JDK1.2版之后提供了WeakReference类来实现弱引用。
虚引用也称为"幽灵引用"或者”幻影引用“。最弱的一种引用关系。无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JKD1.2版之后提供了PhantomReference类来实现虚引用。
5、方法区的垃圾收集主要内容是哪些?
答:废弃的常量和不再使用的类型。
6、分代收集理论是什么?
答:收集器应该将java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数)分配到不同的区域中存储。
根据分代收集理论,java堆可以划分为新生代和老年代。
部分收集(Partial GC)
新生代收集(Minor GC/Young GC):目标只是新生代的垃圾收集
老年代收集(Major GC/Old GC):目标只是老年的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。
混合收集(Mixed GC):目标只是收集整个新生代以及部分老年代。目前只有G1收集器会有这种行为。
整堆收集(Full GC):收集整个java堆和方法区的垃圾收集
7、垃圾收集算法有哪些?
答:从如何判定对象消亡的角度,可以分为“引用计数式垃圾收集”和“追踪式垃圾收集”两大类,也被称为“直接垃圾收集”和“间接垃圾收集”。
《深入理解java虚拟机》一书中主要讨论的都是追踪式垃圾收集。
追踪式垃圾收集可以分为:

  • 标记-清除算法:首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象,也可以反过来。缺点有两个:

    • 执行效率不稳定,标记和清除两个过程的执行效率会随着对象数量增长而降低

    • 内存空间碎片化,会产生大量不连续的内存碎片。程序运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

  • 标记-复制算法

    • 半区复制
      内存按容量划分为大小相等的两块。每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。缺点如下:
      如果内存中多数对象都是存活的,这种算法将会产生大量的内存间复制的开销,
      内存缩小为原来的一半,空间浪费太多。
    • Appel式回收
      新生代分为一块较大的Eden空间和两块较小的Survivor空间,每次分配内存只使用Eden和其中一块Survivor。“逃生门”设计:当Survivor空间不足以容纳一次MinorGC之后存活的对象时,就需要依赖其它内存区域(实际上大多就是老年代)进行分配担保。
  • 标记-整理算法:标记过程和“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后清理掉边界以外的内存。缺点:比如在老年代这种每次回收都有大量对象存活区域,移动存活对象并更新所有引用这些对象的地方将会是一种极为负重的操作。

**

简述一下GC的过程

**
GC在程序员不可控,系统在不可预知的情况下调用System.gc()函数时发生。GC的对象是从GC roots开始搜索而搜索不到,经过一次标记整理后仍然没有复活的这类对象,范围是在java堆和方法区。根据分代收集理论,java堆可以分为新生代和老年代,新生代可以划分为eden区和两个survivor区,默认比例是8:1:1.GC可以根据这个划分分为部分GC和full GC 。其中部分GC又可以分为新生代GC,老年代GC和混合GC.内存分配时只会占用eden区和其中一个survivor区,当这部分内存空间不足时便会触发一次新生代GC,将整理之后仍然存活的对象复制到另一块Survivor,如果这块内存空不足以放下存活对象,则使用老年代担保机制,将对象放到老年代,如果老年代空间仍然不足则会引发一次full GC。以上可以看出新生代使用标记-复制算法,而老年代会使用标记-清除或者标记-整理算法。

下一篇:虚拟机类加载机制——《深入理解java虚拟机》读书笔记

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值