JVM(解读Java 虚拟机)

Posted Panda_Java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM(解读Java 虚拟机)相关的知识,希望对你有一定的参考价值。

JVM学习笔记

1. JVM整体结构

学习JVM的目的:性能调优

1.1. 字节码文件

源代码通过编译器生成.class字节码文件

1.2. 类加载器

1.2.1 加载 Loading

类加载器包括:引导类加载器(BootStrap ClassLoader)、扩展类加载器(Extension ClassLoader)、应用类加载器(Application ClassLoader)

1.引导类加载器(BootStrap ClassLoader启动类加载器):用来加载Java的核心库
/jre/lib/jar包、resource.jar包。负责扩展类加载器和应用类加载器,并指定为
他们的父类加载器。
2.扩展类加载器:java编写,间接派生于ClassLoader类,父类加载器为启动类加载
器。从在JDK的安装目录jre/lib/ext子目录(扩展目录)下加载类库。用户创建的jar
放在此目录下,也会自动由扩展类加载器加载。
3.应用程序类加载器:该类加载是程序中默认的类加载器,一般来说,java应用的类
都是由它完成加载的。
4.自定义加载器:通过继承抽象类Java.lang.ClassLoader类的方式,实现自己的类
加载器,以满足一些特殊的需求。

1.2.2 链接 Linking

Linking 包含三个环节:验证Verify、准备Prepare、解析Reslove

1.2.3 初始化 Initialization

静态变量的初始化

1.3. 运行时数据区 Runtime Data Area

1.3.1 程序计数器

程序计数器:存储指向下一条指令的地址。

程序计数器不存在GCOOM.
除了程序计数器外,其他几个运行时区域的都有可能发生OutOfMemmoryError

1.3.2 虚拟机栈

  1. 虚拟机栈存储着以下内容:栈帧(局部变量表、动态链接、方法返回地址)
  2. 虚拟机栈描述的是Java方法执行的线程内存模型。

1.3.3 本地方法栈

本地方法栈:是为虚拟机使用的本地方法服务。

本地方法栈和虚拟机栈发挥的作用相似的,虚拟机栈为虚拟机执行java方法服务,
而本地方法则是为了虚拟机使用到的本地方法服务。

1.3.4 堆

创建Java对象,存放对象实例。

1.3.5 方法区(Method Area)

方法区:存放被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
注:字符串常量池则存在于方法区。

1.4. 执行引擎

执行引擎:将运行时数据区的指令翻译成机器指令,供CPU执行。

1.4.1 解释器

1.4.2 即时编译器

1.4.3 垃圾回收器

问题:如果自己写一个Java虚拟机的话,主要考虑哪些结构?
答:类加载器和执行引擎

2. 类加载器子系统

2.1类加载器子系统的作用

2.2 类的加载过程

2.3 类的链接过程

2.4 类的初始化

初始化阶段:执行类构造器方法()的过程。

3.双亲委派机制(类加载器涉及双亲委派机制)

3.1 双亲委派机制工作原理

  1. 案例:自定义了一个String类,String str = new String(); 默认调用自定义的String. 蕴含着双亲委派机制。
  2. 双亲委派机制工作原理:

3.2 双亲委派机制优势

  1. 避免类的重复加载
  2. 保护程序安全,防止核心API被随意篡改。(自定义类:java.lang.String)

3.3 沙箱安全机制

4. 运行时数据区(堆:Heap Area)


4.1 堆的核心概述

  1. 描述该图
  2. 所有的线程共享Java堆,在这里还可以划分线程私有的缓冲区(Thread Local Allocation Buffer)TLAB。
  3. java堆的描述:所有的对象实例以及数组都应该在运行时分配在堆上。
  4. 数组和对象永远不会存储在栈上,因为栈帧中保存引用,这个引用指向对象和数组在堆中的位置。
  5. 在方法结束后,堆中的对象不会立马移除,仅仅在垃圾收集的时候才会被移除。
  6. 堆是GC执行垃圾回收的重点区域。

4.2 堆的内存细分

大厂面试jdk8中内存有哪些变化? 堆空间的元空间

4.3 设置堆内存大小与OOM

1.设置堆空间大小的参数
-xms 用来设置堆空间(年轻代和老年代)的初始内存大小
-xmx 最大内存大小

4.4 年轻代与老年代

  1. 年轻代含:伊甸园Eden、Survivor 0(幸存者0区 From)、Survivor 1(To).
  2. 参数设置
    -XX: NewRatio 设置新生代与老年代的比例,默认值是2.
  3. YGC / Minor GC
1. 当伊甸园区满时会触发 Minor GC
2. 年龄计数器age 达到上限阈值,需要晋升到老年代 (默认age = 153. s0 : s1  = 1:1
4. 关于垃圾回收:频繁在新生区收集,很少在养老区收集,几乎不在永久区/元空间收集。

YGC触发时,幸存者会被动进行垃圾回收。

4. FGC / Full GC
老年区满时(或者存放大文件)触发FGC.

4.5 Minor GC、Major GC与Full GC区别

4.6 Full GC 触发机制

触发 Full GC执行的情况有5种:

5. 执行引擎

  1. 执行引擎的概述(视频110)
  2. 执行引擎的工作流程
  3. Java代码编译和执行的过程

6. 垃圾回收算法 GC

6.1 什么是垃圾?

垃圾是指在运行程序中没有任何指针指向的对象。

6.2 为什么需要GC?

1 内存迟早会被消耗完、2 JVM将整理出的内存分配给新的对象(案例 买1w的苹果)、3 应用程序业务庞大,没有GC就不能保证应用程序的正常进行。

6.3 垃圾回收机制

  1. 内存泄漏:内存区由于程序员编码的问题忘记了被回收,导致内存泄漏, 长时间积累—>OOM.
  2. Java中自动内存管理。
  3. GC的作用区域:方法区(元空间)和堆。 程序计数器、java栈、本地方法栈 不存在GC. 程序计数器也不存在溢出OOM.

6.4 垃圾回收相关算法

6.4.1 标记阶段:引用计数算法、可达性分析算法

垃圾标记阶段:对象存活判断-----》对象存活的两种方式:上述的引用计数和可达性分析算法。

6.4.1.1. 引用计数算法

1 定义:对于每个对象保存一个整形的引用计数器属性,用于记录对象被引用的情况。
2 优点:实现简单,判断效率高、回收没有延时性。
3 缺点:存储空间的开销、时间开销 、 无法处理循环引用。
4 循环引用的案例:

6.4.1.2. 可达性分析算法

1 基本思想:

2 哪些对象可以作为GC Roots的对象:
1 虚拟机栈中引用的对象
2 方法区中的类静态属性引用的对象
3 方法区中常量引用的对象
4 本地方法栈JNI(Native方法)引用的对象

6.4.2 清除阶段:标记-清除算法、复制算法、标记-压缩算法

6.4.2.1 标记-清除算法(Mark-Sweep算法)

1 原理

2 案例

3 标记-清除算法的缺点
①2次遍历—>效率不算高;
②在进行GC的时候,需要停止整个应用程序,导致用户体验差;
③这种方式清理出来的·空闲空间内存是不连续的,产生内存碎片。需要维护一个空闲列表。

6.4.2.2 复制算法 (新生代S0和S1区)

1 原理

2 案例

3 复制算法的优缺点

注意适用场景:(存活对象少、垃圾对象多的情况下)大部分对象死亡,少量对象存活 复制到B区,----》新生代区 S0与S1区非常合适。

6.4.2.3 标记-压缩算法(Mark-Compact)

1 背景 :改进于标记-清除法。

2 原理
标记-压缩算法的最终效果等同于标记–清除算法执行后,再进行一次内存碎片整理。

3 优缺点

6.5 对比三种算法

7. 垃圾回收器(待更新…)

7.1 垃圾回收器的分类:

1 按线程数分可以分为串行垃圾回收器和并行垃圾回收器。
适用场景:串行垃圾回收器—单CPU.
案例:
2 按工作模式分可以分并发式垃圾回收器和独占式垃圾回收器
案例:
3 碎片处理方式分可以压缩式和非压缩式垃圾回收器
4 按工作的内存空间分可以分为年轻代和老年代垃圾回收器

7.2 评估GC的性能指标:(重点关注红色)

7.3 Java常见的垃圾收集器有哪些?(经典)


7.4 垃圾收集器的组合关系

7.5 吞吐量与暂停时间对比说明


案例

7.6 Serial收集器(单线程、 复制算法):

新生代单线程收集器,标记和清理都是单线程,优点是简单高效;

7.7 ParNew收集器 (Serial+多线程):

新生代收并行集器,实际上是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现;

7.8 Parallel Scavenge收集器 (多线程复制算法、高效):

新生代并行收集器,追求高吞吐量,高效利用 CPU。吞吐量 = 用户线程时间/(用户线程时间+GC线程时间),高吞吐量可以高效率的利用CPU时间,尽快完成程序的运算任务,适合后台应用等对交互相应要求不高的场景;

7.9 Serial Old收集器 (单线程标记整理算法):

老年代单线程收集器,Serial收集器的老年代版本;

7.10 Parallel Old收集器 (多线程标记整理算法):

老年代并行收集器,吞吐量优先,Parallel Scavenge收集器的老年代版本;

7.11 CMS(Concurrent Mark Sweep)收集器(多线程标记清除算法):

老年代并行收集器,以获取最短回收停顿时间为目标的收集器,具有高并发、低停顿的特点,追求最短GC回收停顿时间。

7.12 G1(Garbage First)收集器 (标记-整理算法):

Java堆并行收集器,G1收集器是JDK1.7提供的一个新收集器,G1收集器基于“标记-整理”算法实现,也就是说不会产生内存碎片。此外,G1收集器不同于之前的收集器的一个重要特点是:G1回收的范围是整个Java堆(包括新生代,老年代),而前六种收集器回收的范围仅限于新生代或老年代。
现在标准:在最大吞吐量优先的情况下,降低停顿时间

7.13 7种经典的垃圾回收器总结

以上是关于JVM(解读Java 虚拟机)的主要内容,如果未能解决你的问题,请参考以下文章

Java 虚拟机 ( JVM ) 概述

Java虚拟机(JVM)概述

JVM内核解读

学术干货|深入浅出解读 Java 虚拟机的差别测试技术

JVM 规范 —— 虚拟机结构

揭秘Java虚拟机:JVM设计原理与实现详细资料大全