JVM导学
什么是JVM?
- 定义
Java Virtual Machine
– Java程序的运行环境(Java二进制字节码的运行环境)
- 好处
- 一次编译,到处运行
- 自动内存管理,垃圾回收功能
- 数组下表越界检查
- 多态
- 比较JVM、JRE、JDK
JVM
(Java Virtual Machine),Java虚拟机JRE
(Java Runtime Environment),Java运行环境,包含了JVM和Java的核心类库(Java API)JDK
(Java Development Kit)称为Java开发工具,包含了JRE和开发工具
学习JVM有什么用?
-
面试 - 理解底层实现原理
- 中高级程序员的必备技能
常见的JVM
JVM 在 Java 中是如何工作的
- JVM主要分为三个子系统
- 类加载器(ClassLoader)
- JVM运行时数据区(内存结构)
- 执行引擎
类加载器系统
- Java 的动态类加载功能由类加载器子系统处理。它在运行时第一次引用一个类时加载、链接和初始化该类,而不是在编译时。
- 它执行三个主要功能
- 加载
- 链接
- 初始化
加载
- 该组件将加载类。
- BootStrap ClassLoader、Extension ClassLoader、Application ClassLoader 是三个有助于实现它的类加载器。
BootStrap ClassLoader
启动类加载器是所有其他类加载器的parent(rt.jar包下的类)Extension ClassLoader
扩展类加载器加载核心 Java 类的扩展类(ext/*.jar包下的类)Application ClassLoader
应用类加载器加载在classpath中的我们自己写的文件
连接
- 这部分要做三件事
-
验证(Verify)
- 验证被加载的类的准确性,保证安全,不被恶意修改
- 有四种验证方式,文件格式验证,元数据验证,字节码验证,符号引用验证
-
准备(Prepare)
- 为类变量分配内存并且设置该类变量的默认初始值,也就是零值,即在准备阶段,类的变量都会是默认值,只有到了初始化阶段(initization),才会赋值
- 如果用final修饰的static变量,那么在这个阶段,就会显示初始化,因为final在编译的时候就分配了空间和值
-
解析(Resolve)
- 将常量池内的符号引用转换为直接引用的过程
- 解析伴随着初始化执行完之后再执行
-
初始化
- 这是类加载的最后阶段,这里所有的静态变量 都将被赋予原始值并执行静态块。
JVM内存结构
方法区(Method Area)
:所有类级别的数据都将存储在这里,包括 静态变量。方法区是每个 JVM 一个,它是一种共享资源。堆(Heap Area)
:所有的Objects及其对应的实例变量 和数组都将存储在这里。堆区也是每个 JVM 一个,因为方法区和堆区为多个线程共享内存,存储的数据不是线程安全的。虚拟机栈(Stack Area)
:对于每个线程,都会创建一个单独的运行时堆栈。对于每个方法调用,都会在堆栈内存中创建一个条目,称为栈帧
。所有局部变量都将在堆栈内存中创建。堆栈区域是线程安全的,因为它不是共享资源。Stack Frame
分为三个子实体如下局部变量数组
:与方法有关,涉及多少个局部变量,相应的值将存储在这里。操作数栈
:如果需要执行任何中间操作,操作数栈充当运行时工作空间来执行操作。帧数据
:所有与方法对应的符号都存储在这里。在任何异常的情况下,catch块信息将在帧数据中维护。
程序计数器(PC Registers)
:每个线程都有独立的程序计数器,用于保存当前执行指令的地址 ,一旦指令执行,程序计数器将被下一条指令更新本地方法栈(Native Method stacks)
:保存本地方法信息。对于每个线程,将创建单独的本地方法堆栈。
执行引擎
- 分配给运行时数据区的字节码将由执行引擎执行。执行引擎读取字节码并逐一执行。
解释器
:读取字节码,解释并逐一执行。解释器解释字节码的速度更快,但执行速度较慢。解释器的缺点是当一个方法调用多次时,每次都需要解释。JIT 编译器
:JIT 编译器抵消了解释器的缺点(一个方法调用多次,每次都需要解释),执行引擎将使用解释器的帮助进行转换,但当它发现重复代码时,它使用 JIT 编译器编译整个字节码并将其更改为本机代码。此本机代码将直接用于提高系统性能的重复方法调用。- 中间代码生成器:生成中间代码
- 代码优化器:负责优化上面生成的中间代码
- 目标代码生成器:负责生成机器代码/本机代码
- Profiler:Profiler是一个特殊的组件,它负责发现热点(即)用于识别方法是否被多次调用。
- 垃圾收集器:垃圾收集器是执行引擎的一部分,它收集/删除未引用的对象。可以通过调用
System.gc()
来触发垃圾收集,但不能保证执行。JVM 的垃圾收集器只收集那些由new关键字创建的对象。因此,如果您创建了任何没有使用new的对象,您可以使用finalize方法来执行清理。
- Java Native Interface(JNI):JNI将与本机方法库交互,并提供执行引擎所需的本机库。
- 本地方法库:这是执行引擎所需的本地库的集合。
评论