转载

JVM 速览

虚拟机:指以软件的方式模拟具有完整硬件系统功能、运行在一个完全隔离环境中的完整计算机系统 , 是物理机的软件实现

JVM 全称 Java Virtual Machine(Java虚拟机),是一个能把 .class字节码 当成 机器码 运行的计算机。

Java虚拟机发展到现在已经不单单是一个虚拟机了,而是一个标准。遵循这个标准,各大公司开发了自己到 jvm 产品,例如

  • Sun HotSpot VM
  • BEA JRockit VM
  • IBM J9 VM
  • Azul VM
  • Apache Harmony
  • Google Dalvik VM
  • Microsoft JVM

以上这些都是 java 虚拟机,那我们常说到 java 虚拟机、jvm 指定又是什么呢?

指的是 Sun HotSpot VM ,这是 sun 公司出品的 jvm,也是JDK 自带的 JVM,sun 公司被 oracle 收购后,现在归 oracle 所有

不管是面试、还是日常交流、还是网上的 jvm 文件,谈论的都是 HotSpot VM,现在大家知道当我们在谈论 jvm 时,我们在谈论什么

启动流程

JVM 速览

基本架构

JVM 速览

Java编译器将源码(.java)编译成字节码,由类加载器加载到jvm中后,进行分析校验,最后由执行引擎执行。

JVM 速览

JVM由三个主要的子系统构成:

  1. 类加载器子系统
  2. 运行时数据区(内存)
  3. 执行引擎

类装载流程

JVM 速览

类加载的生命周期:加载(Loading)-->验证(Verification)-->准备(Preparation)-->解析(Resolution)-->初始化(Initialization)-->使用(Using)-->卸载(Unloading)

类加载器

类加载器又三种

  • Bootstrap(启动类加载器) :它是用本地代码实现的类装入器,负责将 /lib 下面的类库加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
  • Extension(标准扩展类加载器) :负责将/lib/ext 中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
  • System(系统类加载器) :负责将系统类路径(CLASSPATH)中指定的类库(也就是我们写都代码)加载到内存中。开发者可以直接使用系统类加载器。

双亲委派机制

JVM在加载类时默认采用的是双亲委派机制

通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

垃圾收集(GC:Garbage Collection)

自动内存管理,是 java 刚“出道”时的核心“卖点”。而自动内存管理的核心技术就是垃圾收集。

垃圾收集可以简单分为两个阶段

  • 识别垃圾
  • 收集垃圾

垃圾的定义

在 java 中万事万物皆对象,而不再使用的对象就是垃圾。

Java 中的堆是 GC 收集垃圾的主要区域

垃圾识别

主要有两种算法

引用计数法:给每个对象添加一个计数器,当有地方引用该对象时计数器加1,当引用失效时计数器减1。用对象计数器是否为0来判断对象是否可被回收。缺点:无法解决循环引用的问题

可达性分析法:也称根搜索法,通过“GC ROOTs”的对象作为搜索起始点,通过引用向下搜索,所走过的路径称为引用链。通过对象是否有到达引用链的路径来判断对象是否可被回收。

可作为GC ROOTs的对象有虚拟机栈中引用的对象,方法区中类静态属性引用的对象,方法区中常量引用的对象,本地方法栈中JNI引用的对象

分代

垃圾收集的主体是对象,jvm 根据对象所处生命周期的不同阶段, 划分成出 新生代老年代

新生代又划分成 Eden区、survivor区。survivor区又划分出两块空间 From Space 和 To Space。 新生代 中Eden区、 From Space 、 To Space 占比为 8:1:1

GC 针对 新生代老年代 中对象的特点不同,划分出3类GC

  • Minor GC :有的地方又叫 Young GC ,新生代(Young Gen)空间不足时触发收集。由于Java 中的大部分对象通常不需长久存活,新生代是GC收集频繁区域,所以采用 复制算法
  • Full GC :有的地方又叫 Major GCOld GC ,老年代(Old Gen )空间不足时触发收集,由于存放的是大对象及长久存活下的对象,占用内存空间大,回收效率低,所以采用 标记-清除算法

GC算法

按照回收策略划分

标记-清除算法

标记-清除算法分为两阶段, 标记阶段清除阶段

  • 标记阶段 :首先标记出要回收的对象,但不立刻回收
  • 清除阶段 :等待所有要回收的对象都被标记好之后,触发回收

不足之处:

  • 无法处理循环引用的问题
  • 效率不高,需要等待标记完成
  • 产生大量内存碎片(ps:空间碎片太多可能会导致以后在分配大对象的时候而无法申请到足够的连续内存空间,导致提前触发新一轮gc)
JVM 速览

标记-整理算法

标记-整理算法分为 标记阶段整理阶段

  • 标记阶段 :标记出所有要回收的对象
  • 整理阶段 :先将存活对象移到一起,然后清理掉存活对象边界以外的内存
JVM 速览

复制算法

把内存空间划为两个相等的区域,每次只使用其中一个区域。GC 时遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。

算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。

不足之处

  • 内存利用率低
  • 在对象存活率较高时,其效率会变低
JVM 速览

按分区对待划分

增量收集算法

增量收集是一种实时垃圾回收算法,即在应用进行的同时进行垃圾回收。

增量收集把对堆空间划分成一系列内存块,使用时先使用其中一部分,垃圾收集时把之前用掉的部分中的存活对象再放到后面没有用的空间中,这样可以实现一直边使用边收集的效果,避免了传统分代方式整个使用完了再暂停的回收的情况。

分代收集算法

分代收集算法:(商用默认)基于对象生命周期划分为新生代、老年代、元空间,对不同生命周期的对象使用不同的算法进行回收。

JVM 速览

按系统线程划分

串行收集算法

使用单线程处理垃圾回收工作,实现容易,效率较高。

不足之处

  • 无法发挥多处理器的优势
  • 需要暂停用户线程

并行收集算法

使用多线程处理垃圾回收工作,速度快,效率高。理论上CPU数目越多,越能体现出并行收集器的优势。

不足之处:需要暂停用户线程

并发收集算法

垃圾线程与用户线程同时工作。系统在垃圾回收时不需要暂停用户线程

GC收集器常用组合

JVM 速览
JVM 速览

GC日志

JVM 速览
[GC [PSYoungGen: 8192K->1000K(9216K)] 16004K->14604K(29696K), 0.0317424 secs] [Times: user=0.06 sys=0.00, real=0.03 secs]
[GC [PSYoungGen: 9192K->1016K(9216K)] 22796K->20780K(29696K), 0.0314567 secs] [Times: user=0.06 sys=0.00, real=0.03 secs]
[Full GC [PSYoungGen: 8192K->8192K(9216K)] [ParOldGen: 20435K->20435K(20480K)] 28627K->28627K(29696K), [Metaspace: 8469K->8469K(1056768K)], 0.1307495 secs] [Times: user=0.50 sys=0.00, real=0.13 secs]
[Full GC [PSYoungGen: 8192K->8192K(9216K)] [ParOldGen: 20437K->20437K(20480K)] 28629K->28629K(29696K), [Metaspace: 8469K->8469K(1056768K)], 0.1240311 secs] [Times: user=0.42 sys=0.00, real=0.12 secs]
复制代码
原文  https://juejin.im/post/5d75f63ee51d4561c02a25b5
正文到此结束
Loading...