【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堆内存划分为几个固定区域,优先回收垃圾最多的区域

相关推荐
OLDERHARD3 分钟前
Java基础 — 正则表达式+函数式编程
java
CopyLower4 分钟前
安全点的应用场景及其原理详解
jvm·安全
OEC小胖胖5 分钟前
js中正则表达式中【exec】用法深度解读
开发语言·前端·javascript·正则表达式·web
孞㐑¥8 分钟前
C语言—顺序表(含通讯录项目)
c语言·开发语言·经验分享·笔记
学地理的小胖砸12 分钟前
【高分系列卫星简介——高分五号卫星(GF-5)】
开发语言·python·信息可视化·遥感·地理信息
一颗星星辰13 分钟前
Python | 第六章节 | 控制结构
开发语言·网络·python
百锦再16 分钟前
学习Python的难点分析
java·python·学习
灯火不休ᝰ16 分钟前
6--苍穹外卖-SpringBoot项目中菜品管理 详解(二)
java·spring boot·后端
GoppViper18 分钟前
golang 如何生成唯一的 UUID
开发语言·后端·golang·uuid
SkyrimCitadelValinor18 分钟前
python【入门基础知识】
开发语言·python