Learn06-JVM&GC

虚拟机&GC

1.1 并行与并发

并行: 同时运行,多个CPU可以实现真正同时运行
并发: 多个任务交替执行,并未同时

1.2 对象的三种状态

由于finalize的存在,对象可能有三种状态

  1. 可达,(强引用可达、软引用可达、弱引用可达)
  2. 复活:
    * 若覆盖finalize方法,在其中添加代码让对象重新被引用,对象就会复活
    * finalize只会执行一次,第二次不会执行,对象直接变为不可达状态
  3. 不可达状态(准备被GC回收)

1.3 对象的四种引用类型

  • 强引用:String str = new String("1")
  • 软引用:内存不足时会被回收
  • 弱引用:GC启动就被回收
  • 虚引用:被回收时会有通知(也不怎么用)

1.4 线程、栈、堆

一个线程一个栈,而堆是共享的

  • 栈:存储当前线程的相关信息:局部变量程序运行状态方法返回值
  • 堆:只负责存储对象相关信息

1.5 Full GC&Minor GC

MinorGC是年轻代的
System.gc()会导致Full GC执行
还有四种情况也会使Full GC执行:

  • 老年代内存不足
  • 永久代空间溢出
  • CMS GC出现Promotion FailedConcurrent Model Failture
  • Minor GC时晋升的平均大小小于老年代剩余空间大小

1.6 JVM内存模型

Learn06-JVM&GC

1.6.1 方法区、堆、虚拟机栈、本地方法栈、程序计数器

  • 方法区

  • :动态分配大小、耗时比栈多、逻辑上连续,物理空间上不一定连续、线程共享、由GC来回收、JDK 7 后的逃逸分析

    • 逃逸分析:1. 同步消除。(非逃逸的对象直接可以不受同步保护)2. 矢量线程(直接写寄存器)
  • 虚拟机栈:常量池、类型信息、方法信息、域信息等……

  • 本地方法栈:和虚拟机栈差不多,只不过调的是本地方法C++等方法库的方法

  • PC:程序计数器,记录下一条指令。

1.6.2 堆

堆分为两部分:Young、Old

年轻代:Eden、From survivor、To survivor
老年代:Threshold
新生代活下去的进入From&To中,活到“15岁”的进入老年代中,新生代和老年代的GC回收算法不一样。

  • 新生代使用复制回收算法
  • 老年代使用标记-压缩回收算法

1.7 GC回收算法

1.7.1 引用计数法

有引用就+1,反之-1
标记为0时对象被回收
优点:实时回收
缺点:无法处理循环引用(致命缺点)
Learn06-JVM&GC

1.7.2 根搜索算法

从GC Root开始遍历,遍历两次
第一次:标记(不可达对象不一定非死不可,前面说过,因为finalize方法的存在)
第二次:查看是否有必要finalize或者是否已经执行过了finalize,若执行过,则直接不可达

1.7.3 三种算法对比

Learn06-JVM&GC

1.7.3.1 标记-清除算法

速度中,有碎片,它奠定了GC算法的思想

1.7.3.2 复制算法

速度最快,但是要以牺牲一半内存作为代价

1.7.3.3 标记-压缩算法

速度最慢,但没有碎片

1.7.4 增量算法

走走停停,防止了STW(stop the world)一点一点回收,知道GC把垃圾都回收完了
缺点:切换上下文频繁,降低了总耗时以及吞吐量

1.7.5 终极算法——分代收集算法

年轻代和老年代使用不同的算法
年轻代——复制回收算法
老年嗲——标记-压缩算法

1.8 GC性能评价标准

Learn06-JVM&GC

1.9 GC分类

JDK7开始使用G1 GC

Serial/Serial Old
ParNew
Parallel/Paraller Old
Concurrent-Mark-Sweep (CMS)
G1 (Garbage-First)