【Java-JVM】

在学习JVM之前,先了解Java程序执行过程和Java为什么跨平台,有助于我们对JVM的理解。

Java的执行过程:

1. 编译通过Java命令,调用JDK编译器将*.java源文件编译成*.class字节码文件。

2. 执行通过java命令,调用JVM虚拟机,执行*.class字节码文件。

Java程序的跨平台原因:

1. 通用字节码文件JDK编译器在不同平台编译相同源文件的字节码文件都是相同的。

2. 不同版本JVM虚拟机不同平台执行字节码文件会用到不同的JVM虚拟机,将字节码翻译成当前平台可以执行的机器码指令。

JDK、JRE、JVM:

JDK:Java开发工具包,提供javac编译器、jheap、jconsole等监控工具。

JRE:Java运行环境,提供Class Library 核心类库+JVM。

JVM:Java虚拟机,用于运行Java应用程序。

JVM的组成结构:

JVM由JVM解释器、JIT解释编译器、类加载器、运行时数据区、垃圾回收器、本地方法库等部分组成。

1. JVM的执行方式

JVM以解释+编译混合模式,执行字节码文件。

解释执行为主,执行过程中,JVM将每个字节码文件中的每个指令,通过解释器转换成当前平台可以识别的机器码,然后交给CPU执行。

为了提高执行效率,JVM还会在运行期间,JVM通过热点代码的统计分析,识别高频的方法调用,循环体、公共模块等,当超过阈值时,JVM会基于JIT即时编译器(just-in-time compiler )将热点代码转换成机器码,直接交给CPU 执行,提高执行效率。

2. JVM类加载机制

程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载、连接、初始化3个步骤来对该类进行初始化。如果没有意外,JVM将会连续完成3个步骤,所以有时也把这个3个步骤统称为类加载或类初始化。

2.1 类加载过程包含加载、验证、准备、解析和初始化。

1. 加载

这里的「加载」是「类加载」过程的一个阶段,「类加载」描述的是整个过程,「加载」仅表示「类加载」的第一阶段。

在加载阶段,JVM主要完成以下3件事:

1.通过类的完全限定名称获取定义该类的*.class 字节码文件的二进制字节流。

2.将该字节流表示的静态存储结构转换为Metaspace元空间区的运行时存储结构。

3.在内存中生成一个代表该类的Class对象,作为元空间区中该类各种数据的访问入口。

2. 验证

验证是为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。如果验证到输入的字节流不符合 Class 文件格式的约束,虚拟机就会抛出一个 java.lang.VerifyError 异常或其子类异常。

验证阶段大致完成 4 个阶段的检验动作:

文件格式验证

元数据验证

字节码验证

符号引用验证

3. 准备

准备阶段是正式为类变量(static 修饰的变量)分配内存并设置类变量初始值的极端,这些变量所使用的内存都将在方法区中进行分配。注意此时进行内存分配的仅包括类变量,而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在 Java 堆中。

4. 解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程

符号引用:只包含语义信息,不涉及具体实现,以一组符号来描述引用目标,是字面量;符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。

直接引用:与具体实现息息相关,是直接指向目标的指针;直接引用是可以直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在。

5. 初始化

初始化阶段,才真正开始执行类中定义的 Java 程序代码(或者说是字节码)

在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源。

也就是我们通常理解的赋初始值以及执行静态代码块。

2.2 类加载器

在类加载过程的加载阶段,通过类的完全限定名,获取描述类的二进制流的实现类,被称为"类加载器"。

从JVM虚拟机的角度来讲,只存在以下两种不同的类加载器:

1.启动类加载器(Bootstrap ClassLoader ),使用C++实现,是虚拟机的一部分;

2.其它类的加载器,使用Java实现,独立于虚拟机,继承自抽象类java.lang.classLoader。

从Java开发人员的角度可以分为:

1.启动类加载器(Bootstrap ClassLoader):负责将存放在 <JAVA_HOME>\lib 目录中的,或者被 -Xbootclasspath 参数所指定的路径中的,并且是虚拟机识别的(仅按文件名识别,如 rt.jar,名字不符合的类库即使放在 lib 目录中也不会被加载)类库加载到虚拟机内存中。

2.扩展类加载器(Extension ClassLoader):负责加载 <JAVA_HOME>\lib\ext 目录中的,或者被 java.ext.dirs 系统变量所指定的路径中的所有类库。

3.应用程序类加载器(Application ClassLoader):也称为系统类加载器,负责加载用户类路径(ClassPath)上所指定的类库。如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

3. 运行时数据区

JVM虚拟机在执行Java程序的过程中会把它管理的内存划分成若干个不同的数据区域。由方法区、堆区、虚拟机栈、本地方法栈、程序计数器务部分。

JDK 1.8之前分为:线程共享(Heap堆区、Method Area方法区),线程私有(虚拟机栈、本地方法栈、程序计数器)

JDK 1.8之后分为:线程共享(Heap 堆区、MetaSpace 元空间),线程私有(虚拟机栈、本地方法栈、程序计数器)

4. JVM垃圾收集器

分类:

1.按照执行原理分类:

单线程收集器:

Serial垃圾收集器

Serial Old垃圾收集器

多线程收集器:

ParNew垃圾收集器

Parallel Scavenge垃圾收集器

Parallerl Old垃圾收集器

并发收集器:

CMS收集器

G1收集器

2.按照作用区域分类:

新生代:

Serial垃圾收集器

Parallel Scavenge垃圾收集器

ParNew垃圾收集器

老年代:

Serial Old垃圾收集器

Parallerl Old垃圾收集器

CMS收集器

整个Java堆:

G1收集器

具体介绍:

1.Serial垃圾收集器

定义:用于新生代,是单线程收集器,使用复制算法

缺点:单线程完成垃圾回收,在进行垃圾回收时,必须暂停其他所有工作线程,直到垃圾收集结束

2.Serial Old垃圾收集器

定义:用于老年代,是单线程收集器,使用标记整理算法

用途:jdk5.0之前版本与新生代Parallerl Scavenge收集器搭配使用

在老年代中作为CMS收集器的后备垃圾收集方案

3.ParNew垃圾收集器

定义:多线程收集器,使用复制算法,是JVM在Server模式下新生代的默认垃圾回收器

缺点:和Serial一样,多线程进行垃圾回收时也要暂停其他所有工作线程

4.Parallerl Scavenge收集器

定义:多线程垃圾收集器,使用复制算法,用于新生代中

优点:使得程序达到一个可控的吞吐量,高吞吐量能够最高效率利用CPU时间;采用自适应调节策略

5.Parallel Old收集器

定义:用于老年代,使用标记整理算法,是多线程垃圾收集器

用处:能够在老年代提供吞吐量优先的垃圾收集器

6.CMS收集器

定义:CMS(Concurrent mark sweep),用于老年代的多线程垃圾收集器,使用标记清除算法,属于并发执行的垃圾收集器

作用:获取最短垃圾回收停顿时间,从而提高用户体验

过程:

初始标记:标记GC Roots能直接管理的对象,需要暂停所有工作线程

并发标记:进行GC Roots跟踪,和用户线程一起工作,无需暂停工作线程

重新标记:修正在并发标记期间,因用户程序工作导致标记变动的标记记录

并发清除:清楚GC Roots不可达对象,无需暂停工作线程

7.G1收集器

定义:G1(Garbage First)使用标记整理算法

优点:不会产生内存碎片

可以精确控制停顿时间,实现低停顿的垃圾回收

将整个Java堆内存划分为几个固定区域,优先回收垃圾最多的区域

相关推荐
2401_857439691 小时前
SSM 架构下 Vue 电脑测评系统:为电脑性能评估赋能
开发语言·php
SoraLuna2 小时前
「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台
开发语言·macos·ui·华为·harmonyos
xlsw_2 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
Dream_Snowar3 小时前
速通Python 第三节
开发语言·python
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭3 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫3 小时前
泛型(2)
java
超爱吃士力架4 小时前
邀请逻辑
java·linux·后端
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石4 小时前
12/21java基础
java