JAVA虚拟机(JVM)学习

入门

什么是JVM

JVM:Java Virtual Machine,Java虚拟机。

JVM是JRE(Java Runtime Environment)的一部分,安装了JRE就相当于安装了JVM,就可以运行Java程序了。JVM的作用:加载并执行Java字节码(.class)文件。

常见的JVM


Java虚拟机要实现Java虚拟机规范,它定义了Java虚拟机的结构、指令集、类文件格式、类加载器、字节码执行引擎等方面的内容。

JVM结构



执行引擎Execution Engine

JVM执行引擎通常由两个主要组成部分构成:解释器和即时编译器(Just-In-Time Compiler,JIT Compiler)。

解释器:当Java字节码被加载到内存中时,解释器逐条解析并直接执行字节码指令。

即时编译器(JIT Compiler):即时编译器将字节码动态地编译为本地机器码,之后再执行。即时编译器根据运行时的性能数据和优化技术,对经常执行的热点代码进行优化,从而提高程序的性能。即时编译器可以将经过优化的代码缓存起来,以便下次再次执行时直接使用。

本地方法接口Native Interface

本地接口的作用是融合不同的编程语言为 Java 所用。当Java代码调用本地方法 (被native所修饰的方法)时,JVM会将控制权转移到本地方法实现所在的本地库本地库 是一个包含本地方法实现的动态链接库(DLL - windows函数库)或共享对象文件(SO - Linux函数库)。它是使用其他编程语言编写的,通常是为了与底层操作系统或硬件进行交互。本地库可以通过JNI加载到JVM中,并提供给Java代码调用。

例如Thread类中有一些标记为native的方法 操作底层操作系统线程

本地方法栈Native Method Stack

本地方法栈(Native Method Stack):本地方法栈存储了从Java代码中调用本地方法时所需的信息。是线程私有 的。

本地方法栈是JVM专门为调用非Java语言方法而设计的,它与操作系统和硬件交互,通过JNI为Java程序提供更强大的功能。每个线程都有自己的本地方法栈,保证本地方法的调用是独立且线程安全的。

PC寄存器(程序计数器PC Register)

PC寄存器(程序计数器,Program Counter Register)是JVM中线程私有 的一块小内存区域。用于记录当前线程 正在执行的字节码指令的地址或行号。它类似于一个指针,指向线程正在执行的字节码指令的下一条指令。

类加载器ClassLoader

类加载器(ClassLoader)是JVM的一个关键组件,用于动态加载、链接和初始化Java类。它的主要职责是在程序运行时将类的字节码加载到JVM中,以便JVM可以执行这些类。类加载器是一个负责加载类的对象,用于实现类加载过程中的加载这一步。每个 Java 类都有一个引用指向加载它的 ClassLoader。数组类不是通过 ClassLoader 创建的(数组类没有对应的二进制字节流),是由 JVM 直接生成的。

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,即双亲委派模型

虚拟机栈stack

栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,每个线程都有自己的栈,它的生命周期是跟随线程的生命周期,线程结束栈内存也就释放,是线程私有 的。线程上正在执行的每个方法都各自对应一个栈帧 (Stack Frame)。

JVM对Java栈的操作只有两个,就是对栈帧的压栈和出栈,遵循"先进后出"或者"后进先出"原则。

一个线程中只能由一个正在执行的方法(当前方法),因此对应只会有一个活动的当前栈帧。

栈溢出(StackOverflowError):通常在递归调用

栈帧

栈帧是一个内存区块,是一个数据集,包含方法执行过程中的各种数据信息。

局部变量表(Local Variables)

也叫本地变量表。存储方法参数和方法体内的局部变量:8种基本类型变量、对象引用(reference)。

操作数栈(Operand Stack)

作用:也是一个栈,在方法执行过程中根据字节码指令记录当前操作的数据,将它们入栈或出栈。用于保存计算过程的中间结果,同时作为计算过程中变量的临时存储空间。

java 复制代码
public class OperandStackDemo {
    public static void main(String[] args) {
        int i = 15;
        int j = 8;
        int k = i + j;
    }
}


动态链接(Dynamic Linking)

作用:可以知道当前帧执行的是哪个方法。指向运行时常量池中方法的符号引用。程序真正执行时,类加载到内存中后,符号引用会换成直接引用。

方法返回地址(Return Address)

可以知道调用完当前方法后,上一层方法接着做什么,即"return"到什么位置去。存储当前方法调用完毕后下一条指令的地址

完整一个线程内存结构

java -Xss 可以设置栈大小

方法区Method Area

被所有线程共享,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等

堆heap

堆是线程共享

堆、栈、方法区的关系

HotSpot是使用指针的方式来访问对象:

  • 内存用于存放对象和数组
  • 中会存放指向对象类型数据的地址
  • 中会存放指向堆中的对象的地址

堆空间

一个Java程序运行起来对应一个进程,一个进程对应一个JVM实例,一个JVM实例中有一个运行时数据区。

在 Java 虚拟机(JVM)中,堆空间是管理 Java 对象的内存区域。堆空间的主要作用是动态分配和管理 Java 对象的内存,在JVM启动的时候被创建,并且一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。

堆空间划分

堆内存逻辑上分为三部分:

  • Young Generation Space 新生代/年轻代 Young/New
  • Tenured generation space 老年代/养老代 Old/Tenured
  • Permanent Space/Meta Space 永久代/元空间 Permanent/Meta

新生代又划分为:

  • 伊甸园区(Eden space)
  • 和幸存者区(Survivor space) 。
    幸存者区有两个:
  • S0区(Survivor 0 space)
  • S1区(Survivor 1 space)

堆内存内部空间所占比例:

  • 新生代与老年代的默认比例: 1:2
  • 伊甸园区与幸存者区的默认比例是:8:1:1

配置堆大小

-Xms600m -Xmx600m -Xmn200m

  • Xms表示堆的起始内存,等价于-XX:InitialHeapSize,默认是物理电脑内存的1/64。

  • Xmx表示堆的最大内存,等价于-XX:MaxHeapSize,默认是物理电脑内存的1/4。

    通常会将-Xms和-Xmx配置相同的值,目的是为了在Java垃圾回收机制清理完堆区后,不需要重新分隔计算堆区的大小,从而提高性能。

JDK1.8及之后堆空间

堆空间工作流程

学不明白的了解即可

垃圾回收GC

在C/C++这类没有自动垃圾回收机制的语言中,一个对象如果不再使用,需要手动释放,Java中为了简化对象的释放,引入了自动的垃圾回收(Garbage Collection简称GC)机制。通过垃圾回收器来对不再使用的对象完成自动的回收,垃圾回收器主要负责对堆上的内存进行回收。其他很多现代语言比如C#、Python、Go都拥有自己的垃圾回收器

线程不共享的部分,都是伴随着线程的创建而创建,线程的销毁而销毁。因此线程不共享的程序计数器、虚拟机栈、本地方法栈中没有垃圾回收。

方法区的垃圾回收

方法区中能回收的内容主要就是不再使用的类。判定一个类可以被卸载。需要同时满足下面三个条件:

1、此类所有实例对象没有在任何地方被引用,在堆中不存在任何该类的实例对象以及子类对象。

2、该类对应的 java.lang.Class 对象没有在任何地方被引用。

3、加载该类的类加载器没有在任何地方被引用。

堆的垃圾回收

Java堆中的对象是否能被回收,是根据对象是否被引用来决定的。如果对象被引用了,说明该对象还在使用,不允许被回收。

垃圾判断

判断堆上的对象是否被引用方法:引用计数法(已摒弃)和可达性分析法。

可达分析法

将一系列GC Root的集合作为起始点,按照从上至下的方式搜索所有能够被该合集引用到的对象(是否可达),并将其加入到该和集中,这个过程称之为标记(mark),被标记的对象是存活对象。 最终,未被探索到的对象便是死亡的,可以回收的。

垃圾回收算法

当成功区分出内存中存活对象和死亡对象后,GC接下来的任务就是执行垃圾回收。有以下算法:

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

复制算法(Copying)

标记压缩算法(Mark-Compact)

分代收集算法(Generational-Collection)

垃圾收集器

如果说收集算法是内存回收的方法论,垃圾收集器就是内存回收的具体实现

七款经典垃圾收集器:

算法和收集器了解即可

相关推荐
向哆哆1 分钟前
Java 企业级应用:SOA 与微服务的对比与选择
java·开发语言·微服务
江拥羡橙2 分钟前
2025年,HarmonyOS认证学习及考试
学习·华为·harmonyos·鸿蒙·华为证书·harmonyos认证·华为证书考试
登登登__6 分钟前
MongoDB
java
ππ记录30 分钟前
java面试题带答案2025最新整理
java·开发语言
PHASELESS41132 分钟前
Java栈与队列深度解析:结构、实现与应用指南
java·开发语言·算法
Huazie1 小时前
flea-cache使用之Redis哨兵模式接入
java·redis·开源
啊阿狸不会拉杆1 小时前
数据结构-限定性线性表 - 栈与队列
java·c语言·数据结构·c++·python·算法
追梦No12 小时前
Flink回撤流详解 代码实例
java·服务器·flink
你们补药再卷啦2 小时前
newbee商城购物车模块mapper.xml
java·数据库·sql
开开心心就好2 小时前
功能丰富的PDF处理免费软件推荐
java·windows·python·pdf·电脑·生活·软件需求