JAVA复习:GC垃圾收集器

学习内容来自尚硅谷宋红康老师的JVM教程

https://www.bilibili.com/video/BV1PJ411n7xZ/

垃圾是什么?指运行程序中没有任何指针指向的对象

不清理垃圾有什么后果?垃圾对象占用内存空间,容易内存溢出。

内存溢出和内存泄露的区别,

  • 内存溢出很容易来理解, 内存不够用,是指在程序申请内存时,没有足够的内存提供就出现了内存溢出
  • 内存泄漏 但是程序在申请内存后,无法释放已申请的内存空间 如java的数据库连接或者网络连接没有及时close。
  • 当内存泄露越来越多的时候,最终会导致内存溢出

JAVA 的垃圾回收机制

自动内存管理,(分配和回收)开发人员就不同过多关注内存的分配和释放,降低了内存的泄露和溢出。

java堆是垃圾回收的重点。青年区->老年区->永久代 回收频率依次减少

垃圾回收的算法

垃圾标记阶段:引用计数算法和可达性分析算法

引用计数器算法,每个对象保存一个整形的应用计数器,记录对象自身被引用的次数。

优点:实现简单,垃圾对象容易识别,判定效率高,回收没有延迟

缺点:额外的空间,更新计数器额外的时间开销。无法处理循环引用的情况(内存泄露,致命的缺点,因此java没有采用)

可达性分析/根搜索/追踪性垃圾收集算法

对象的finalization机制

对象要被gc回收之前会执行finalize方法,定义在Object类中的方法。可以在里面重写一些资源释放的方法。

但是不要主动去调用这个方法。

对象的三种状态

清除阶段的三种算法:

  • 标记-清除算法
  • 复制算法
  • 标记-压缩算法

标记-清除算法

标记从Gc roots开始遍历,标记所有可达到的对象(在对象的Header中记录为可达对象)

对堆中所有对象进行遍历,清除没有标记的对象。

缺点:效率不高,在进行GC的时候,需要停止整个应用程序,影响用户体验(Stop the world),容易产生内存碎片。需要维护一个空闲列表。

清空就是将对象的地址记录到空闲列表上。

复制算法:

优点:没有标志和消除过程,高效,不会产生碎片问题

缺点:需要两倍内存空间,需要维护对象之间的引用关系,如果大部分对象都不是垃圾,移动对象的时间开销也会很大

标记-压缩(标记-整理)算法

复制算法高效性的前提是垃圾对象多,存活对象少。而这很符合年轻代中数据的特点。但是老年代就不一样了,老年代的数据大部分是存活数据。

优点:没有内存碎片,不需要维护空闲列表,比复制算法空间利用率高

缺点:效率低,要维护对象间的引用,需要STW,影响用户体验

对比

分代收集算法:具体问题具体分析

青年代用复制算法,同时设置伊甸园区和幸存者区缓解内存的浪费。

老年代用标记-清除和标记-整理混合的方法。

增量收集算法:

缺点:造成垃圾回收总体成本提高,系统吞吐量下降。因为切换线程和上下文转换有额外开销。

分区算法:

一些概念:

System.gc() /Runtime.getRuntion().gc(),可能触发Full GC,对老年代和青年代进行回收。但是无法保证立刻调用垃圾收集器,会在程序执行的某个不确定时间节点进行调用。

System.runFinalization(); 会强制调用失去引用对象的finalize方法。

内存溢出 OOM:没有空闲空间,并且垃圾回收之后还是不够。

内存泄露 Memory Leak:对象不会再被程序使用了,但是GC又无法回收了。通常是编码过程的疏忽,导致某些对象的生命周期过长。

内存泄露的两个例子。

STW stop the world 所有的垃圾收集器都会有这个情况。就是把所有用户进程停止,执行垃圾回收。

并发(concurrent)实际上就是同步,某个时刻只有一个程序在执行,只是CPU快速地切换,让我们感觉同时在执行。

并行(Parallel) 同一个时刻,多个程序在真正运行。

  • 垃圾回收的并行:多条垃圾回收线程并行执行。
  • 垃圾回收的串行:只有一个垃圾回收器线程执行。
  • 垃圾回收器的并发:用户线程和垃圾回收线程同时执行。

安全点:

安全区域:

引用(前提都是可达的对象引用)

强引用对象不会被gc回收,也是内存泄露的主要原因。

软引用,内存足够不会回收,内存不够时,在二次gc时被回收。

弱引用:被gc就回收

JDK更新可以从三个层面区关注:

  • 语法层面
  • API层面
  • 底层优化

垃圾回收器的分类:

  • 按线程数分:串行gc和并行gc
  • 按照工作模式:并发式和独占式
  • 按碎片分:压缩式和非压缩式
  • 按工作内存:年轻代gc和老年代gc

GC的性能评估指标

上面标红的三项是主要的,但也是互相制约的。

主要关注前两项

吞吐量与暂停时间的矛盾。

可以在JVM参数中设置Parallel GC的吞吐量或者暂停时间的参数。

发表评论

电子邮件地址不会被公开。 必填项已用*标注