【JVM】一篇文章彻底理解JVM的组成,各组件的底层实现逻辑

在这里插入图片描述

文章目录

    • JVM 的主要组成部分
    • 类加载器(Class Loader)
      • 1. 加载(Loading)
      • 2. 链接(Linking)
      • 3. 初始化(Initialization)
    • Execution Engine(执行引擎)
      • 1. 解释器(Interpreter)
      • 2. 即时编译器(JIT Compiler)
      • 3. 垃圾回收器(Garbage Collector)
    • Runtime Data Area(运行时数据区)
      • 1. 方法区(Method Area)
      • 2. 堆(Heap)
      • 3. Java 虚拟机栈(Java Virtual Machine Stack)
      • 4. 程序计数器(Program Counter Register)
      • 5. 本地方法栈(Native Method Stack)
    • Native Interface(本地接口)
    • java文件在jvm中的处理过程
    • 堆中实现深拷贝与浅拷贝原理
    • 对象分配内存底层原理

更多相关内容可查看

JVM 的主要组成部分

JVM包含两个子系统和两个组件,两个子系统为Class loader(类装载)、Execution engine(执行引擎);两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。

对于某些面试官可能就会问到这些组成的原理,下文将详细介绍这四部分

类加载器(Class Loader)

在这里插入图片描述

  • 功能:负责加载 Java 类文件到 JVM 中。它的主要任务是找到、加载、链接和初始化类。
  • 过程
    • 加载:从文件系统、网络或其他源中读取文件。
    • 链接
      • 验证:确保字节码符合 JVM 的规范。
      • 准备:分配内存并设置类变量的初始值。
      • 解析:将符号引用转换为直接引用。
    • 初始化:执行静态初始化块和静态变量赋值。

1. 加载(Loading)

  • 定义:类加载的第一步是查找并加载 .class 文件。
  • 来源:加载可以来自多个地方,包括:
    • 文件系统(本地磁盘)
    • 网络(远程服务器)
    • 其他类加载器(如应用程序特定的加载器)
  • 实现:类加载器会读取字节流并将其转换为数据结构,以供后续处理。

对于java来说,类加载器将.class文件(字节码二进制的数据),装载到jvm中,并将类的结构封装成一个class对象放到堆中

2. 链接(Linking)

a. 验证(Verification)

  • 目的:确保加载的字节码符合 JVM 的规范,防止潜在的安全问题和错误。
  • 检查内容
    • 字节码的合法性,确保它符合 Java 虚拟机规范。
    • 确保类的结构正确,如方法的参数和返回类型等。

b. 准备(Preparation)

  • 目的:为类变量(静态变量)分配内存并设置初始值。
  • 内存分配:为类的静态字段分配内存,这些字段在方法区的运行时数据区中存储。
  • 默认值:所有类变量在准备阶段会被初始化为默认值(如 0nullfalse)。

c. 解析(Resolution)

  • 目的:将符号引用转换为直接引用。
  • 符号引用:在字节码中,类、方法和字段等通过符号名引用。
  • 直接引用:解析后,符号引用被转换为内存地址(直接引用),使得 JVM 在运行时可以直接访问。

3. 初始化(Initialization)

  • 定义:在链接完成后,类的初始化阶段会执行。
  • 执行过程
    • 执行类的静态初始化块。
    • 为静态变量赋值,通常是在定义时指定的值。
  • 静态初始化块:如果类中有静态代码块,这些代码会在初始化阶段执行,允许开发者在类加载时执行特定逻辑。

Execution Engine(执行引擎)

在这里插入图片描述

功能:负责执行字节码,将其转换为底层机器指令并由 CPU 执行。(jvm其实是无法识别字节码的,所以要转一下)

主要组成

  • 解释器(Interpreter):逐行解释字节码并执行,适合快速启动,但效率较低。
  • 即时编译器(JIT Compiler):将热点代码(经常执行的代码)编译为机器码,提高执行效率。编译后的代码存储在内存中,以供后续直接调用。
  • 垃圾回收器(Garbage Collector):负责自动管理内存,回收不再使用的对象,防止内存泄漏。

1. 解释器(Interpreter)

  • 功能:解释器逐行读取和执行Java字节码,而不是将整个字节码文件编译为机器码。这使得程序可以快速启动和运行。
  • 工作原理
    • 逐行解析:解释器将字节码指令逐行读取,解析每条指令并立即执行。对于每个字节码操作,都会进行相应的操作(如计算、对象创建等)。
    • 适用场景:适合小型应用或在开发阶段,快速迭代和测试代码时。
  • 优缺点
    • 优点:启动快,不需要预编译,适合动态变化的代码。
    • 缺点:整体执行效率低,因为每次运行都需要解析和执行字节码,增加了开销。

2. 即时编译器(JIT Compiler)

  • 功能:JIT编译器在运行时将热点代码(频繁执行的代码段)编译为机器码,从而提高执行效率。
  • 工作原理
    • 热点识别:JIT编译器监测哪些代码被频繁调用,并将这些代码编译为本地机器码。
    • 优化执行:编译后的机器码会存储在内存中,后续执行时直接调用,避免再次解析字节码。
    • 实时优化:JIT编译器还可以进行多种优化(如内联、死代码消除等),进一步提高性能。
  • 优缺点
    • 优点:执行速度快,减少了解释执行的开销,适合长时间运行的应用。
    • 缺点:初次执行时可能存在延迟,因为需要时间编译热点代码;占用更多内存以存储编译后的代码。

3. 垃圾回收器(Garbage Collector)

后续会单独写一篇有关垃圾回收器的文章

  • 功能:自动管理内存,回收不再使用的对象,防止内存泄漏和优化内存使用。
  • 工作原理
    • 对象标记:垃圾回收器会跟踪所有对象的引用情况,标记那些不再被引用的对象。
    • 清理:标记完成后,垃圾回收器会清理这些不再使用的对象,释放内存。
    • 回收算法:常见的回收算法包括标记-清除、复制、标记-压缩等,不同的算法有不同的效率和内存使用特点。
  • 优缺点
    • 优点:自动管理内存,开发者无需手动释放内存,降低了内存管理的复杂性。
    • 缺点:可能导致性能波动,尤其是在垃圾回收时,可能会暂停应用程序的执行(称为“停顿”现象)。

Runtime Data Area(运行时数据区)

在这里插入图片描述

  • 功能:JVM 在运行 Java 程序时使用的内存区域,主要包括:
    • 方法区:存储类信息、常量、静态变量等。
    • :用于存储对象实例和数组,是所有线程共享的。
    • Java 虚拟机栈:每个线程都有独立的栈,用于存储局部变量、方法调用等。
    • 程序计数器:指示当前执行的字节码指令位置。
    • 本地方法栈:用于处理本地方法调用。

1. 方法区(Method Area)

  • 功能:方法区是JVM的一部分,用于存储类信息、常量、静态变量、即时编译后的代码等。它是所有线程共享的内存区域。
  • 内容
    • 类信息:存储类的结构,如类的名称、访问修饰符、父类信息、接口信息等。
    • 常量池:存储编译时生成的常量,包括字符串字面量和其他基本数据类型的常量。
    • 静态变量:存储用static修饰的变量,这些变量在整个类的生命周期内是共享的。
  • GC(垃圾回收):方法区也会进行垃圾回收,特别是对于常量池中的无用常量。

2. 堆(Heap)

  • 功能:堆是JVM中最大的内存区域,用于存储对象实例和数组。它是所有线程共享的,适合动态分配内存。
  • 内容
    • 对象实例:通过new关键字创建的对象。
    • 数组:存储所有类型的数组(如整型数组、对象数组等)。
  • GC(垃圾回收):堆中的内存管理是JVM的主要任务之一,使用不同的垃圾回收算法(如标记-清除、复制等)来回收不再使用的对象。

3. Java 虚拟机栈(Java Virtual Machine Stack)

  • 功能:每个线程都有独立的虚拟机栈,存储局部变量、方法调用和返回值。栈的生命周期与线程相同。
  • 内容
    • 局部变量:存储方法参数和局部变量,包括基本数据类型和对象引用。
    • 方法调用:每次方法调用时会创建一个栈帧,保存当前方法的信息和状态。
  • 栈溢出:如果栈深度超过JVM允许的最大值,将会抛出StackOverflowError

4. 程序计数器(Program Counter Register)

  • 功能:每个线程都有一个独立的程序计数器,用于指示当前执行的字节码指令的位置。它是线程私有的。
  • 内容
    • 指令地址:记录当前线程正在执行的字节码指令地址。
    • 线程切换:当线程切换时,程序计数器的值可以帮助恢复执行状态。

5. 本地方法栈(Native Method Stack)

  • 功能:本地方法栈用于处理 Java 程序中调用的本地方法(使用 JNI,即 Java Native Interface)。
  • 内容
    • 本地方法调用:存储本地方法的参数和局部变量。
    • JNI支持:可以直接调用 C/C++ 等语言编写的底层方法。
  • 栈溢出:类似于虚拟机栈,如果本地方法栈的深度超过JVM设定的最大值,将会抛出StackOverflowError

Native Interface(本地接口)

  • 功能:允许 Java 代码调用其他语言(如 C/C++)编写的本地方法。这使得 Java 可以利用系统级资源或优化性能。
  • 相关工具
    • Java Native Interface (JNI):是 Java 提供的标准机制,允许 Java 代码和本地应用程序相互调用。

java文件在jvm中的处理过程

1.java文件,通过java源码编译器,Java 源代码经过编译后生成 `.class文件,存储的是字节码(二进制数据)。

2.类加载器将字节码数据读到方法区中,并在堆中创建一个java.lang.Class对象,用来封装类在方法区内的数据结构

3.而字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行

4.在某些情况下,执行过程中需要调用本地库(Native Interface)来实现特定功能。

整体流程总结:
.java文件通过java源码编译器进行编译为.class文件,存储的是字节码(二进制数据),类加载器,通过验证、准备、解析、初始化流程、将字节码数据读到方法区中,并在堆中创建一个java.lang.Class对象,用来封装类在方法区内的数据结构,通过编译器,将字节码翻译成底层系统指令,再交由 CPU 去执行

堆中实现深拷贝与浅拷贝原理

浅拷贝只复制对象的基本属性,而引用属性仍指向原对象。

class Address {String city;public Address(String city) {this.city = city;}
}class Person implements Cloneable {String name;Address address;public Person(String name, Address address) {this.name = name;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}public class ShallowCopyExample {public static void main(String[] args) throws CloneNotSupportedException {Address addr = new Address("New York");Person p1 = new Person("Alice", addr);Person p2 = (Person) p1.clone();System.out.println(p1.address.city); // 输出: New Yorkp2.address.city = "Los Angeles";System.out.println(p1.address.city); // 输出: Los Angeles (引用共享)}
}

深拷贝复制对象及其引用的所有属性,确保没有共享引用。

class Address {String city;public Address(String city) {this.city = city;}public Address deepCopy() {return new Address(this.city);}
}class Person implements Cloneable {String name;Address address;public Person(String name, Address address) {this.name = name;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {Person cloned = (Person) super.clone();cloned.address = this.address.deepCopy(); // 深拷贝return cloned;}
}public class DeepCopyExample {public static void main(String[] args) throws CloneNotSupportedException {Address addr = new Address("New York");Person p1 = new Person("Alice", addr);Person p2 = (Person) p1.clone();System.out.println(p1.address.city); // 输出: New Yorkp2.address.city = "Los Angeles";System.out.println(p1.address.city); // 输出: New York (无引用共享)}
}
浅拷贝就是平常对于一个实例的属性赋值,重新set就会覆盖原来的 深拷贝不会覆盖原来的属性值,而是会生成一个新的实例

对象分配内存底层原理

给对象分配内存有两种方式:

  • 指针碰撞:意思就是如果Java堆的内存是规整,即所有用过的内存放在一边,而空闲的的放在另一边。分配内存时将位于中间的指针指示器向空闲的内存移动一段与对象大小相等的距离,这样便完成分配内存工作
  • 空闲列表:如果Java堆的内存不是规整的,则需要由虚拟机维护一个列表来记录那些内存是可用的,这样在分配的时候可以从列表中查询到足够大的内存分配给对象,并在分配后更新列表记录。

在这里插入图片描述

可能存在的并发安全问题:可能出现正在给对象 A 分配内存,指针还没来得及修改,对象 B 又同时使用了原来的指针来分配内存的情况

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1545149.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot+Vue+MySQL的美食点餐管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 在数字化快速发展的今天,餐饮行业也迎来了转型升级的重要机遇。传统餐饮管理方式面临效率低下、顾客体验不佳等问题。为此,开发一款基于SpringBootVueMySQL架构的美食点餐管理系统显得尤为重要。该系统旨…

详解机器学习经典模型(原理及应用)——岭回归

一、什么是岭回归 岭回归(Ridge Regression),也称为Tikhonov正则化(Tikhonov Regularization),是一种专门用于处理多重共线性(特征之间高度相关)问题的线性回归改进算法,…

Go Mail设置指南:如何提升发送邮件效率?

Go Mail使用技巧与配置教程?如何用Go Mail实现发信? 随着工作负载的增加,如何高效地发送和管理邮件成为了许多职场人士面临的挑战。AokSend将为您提供一份详细的Go Mail设置指南,帮助您提升发送邮件的效率,让您的邮件…

Java网络编程、正则表达式、单例设计模式与Lombok

目录 Java网络编程、正则表达式、单例设计模式与Lombok Java网络编程 软件结构 网络基础知识 相关概念 IP地址 TCP协议和UDP协议介绍 TCP协议的三次握手和四次挥手 UDP协议编程 创建客户端 创建服务端 运行 TCP协议编程 创建客户端 创建服务端 运行 文件上传案例 创建客户端 创…

风力发电机叶片表面缺陷识别检测数据集yolo数据集 共7000张

风力发电机叶片表面缺陷识别检测数据集yolo数据集 共7000张 风力发电机叶片表面缺陷识别数据集(Wind Turbine Blade Defects Recognition Dataset, WTBDRD) 摘要 WTBDRD 是一个专门为风力发电机叶片表面缺陷识别而设计的数据集,旨在为相关领…

OpenAPI鉴权(二)jwt鉴权

一、思路 前端调用后端可以使用jwt鉴权;调用三方接口也可以使用jwt鉴权。对接多个三方则与每个third parth都约定一套token规则,因为如果使用同一套token,token串用可能造成权限越界问题,且payload交叉业务不够清晰。下面的demo包…

探索图像生成大模型Imagen:从理论到代码实践

一、引言 在当今的人工智能领域,图像生成技术取得了令人瞩目的进展。其中,Imagen作为一款强大的图像生成大模型,吸引了众多研究者和开发者的目光。它能够生成高质量、逼真的图像,为艺术创作、游戏开发、虚拟现实等众多领域带来了无…

数据集-目标检测系列-老虎检测数据集 tiger>> DataBall

数据集-目标检测系列-老虎检测数据集 tiger>> DataBall 数据集-目标检测系列-老虎检测数据集 tiger 数据量:6k 想要进一步了解,请联系。 DataBall 助力快速掌握数据集的信息和使用方式,享有百种数据集,持续增加中。 数据…

【算法】模拟:(leetcode)6.Z 字形变换(medium)

目录 题目链接 题目介绍 解法 1、模拟: 2、找矩阵中的规律: 公差 第一行和最后一行 中间行 代码 题目链接 6. Z 字形变换 - 力扣(LeetCode) 题目介绍 解法 1、模拟: 采用模拟的思想,按照Z字形&…

太速科技-383-基于kintex UltraScale XCKU060的双路QSFP+光纤PCIe 卡

基于kintex UltraScale XCKU060的双路QSFP光纤PCIe 卡 一、板卡概述 本板卡系我司自主研发,基于Xilinx UltraScale Kintex系列FPGA XCKU060-FFVA1156-2-I架构,支持PCIE Gen3 x8模式的高速信号处理板卡,搭配两路40G QSFP接口&#xff…

dev containers plugins for vscode构建虚拟开发环境

0. 需求说明 自用笔记本构建一套开发环境,用docker 虚拟插件 dev containers,实现开发环境的构建,我想构建一套LLMs的环境,由于环境配置太多,不想污染本地环境,所以选择隔离技术 1. 环境准备 vscodedocker 2. 步骤…

Xilinx 使用DDS实现本振混频上下变频

文章目录 一、什么是混频?二、为什么要进行混频?三、Matlab实现混频操作四、FPGA实现混频上下变频操作4.1 例化IP4.2 仿真验证 一、什么是混频? 混频(Mixing)是信号处理中的一个核心概念,混频的本质是将两个…

C语言 | Leetcode C语言题解之第435题无重叠区间

题目: 题解: int cmp(int** a, int** b) {return (*a)[1] - (*b)[1]; }int eraseOverlapIntervals(int** intervals, int intervalsSize, int* intervalsColSize) {if (intervalsSize 0) {return 0;}qsort(intervals, intervalsSize, sizeof(int*), cm…

Git版本控制的使用教程

使用Git进行项目代码的版本控制,具体操作: 1). 创建Git本地仓库 当Idea中出现: 说明本地仓库创建成功。 2). 创建Git远程仓库 访问Gitee - 基于 Git 的代码托管和研发协作平台,新建仓库 点击 创建 3). 将本地文件推送到Git远程…

typename、非类型模板参数、模板参数的特化、模板类成员函数声明和定义分离、继承等的介绍

文章目录 前言一、typename二、非类型模板参数三、模板参数的特化1. 函数模板参数的特化2. 类模板的特化 四、模板类成员函数声明和定义分离1. 显示实例化(不建议使用)2. 将生命和定义写在同一个.h文件中 五、 继承总结 前言 typename、非类型模板参数、…

基于DAMODEL——Faster-RCNN 训练与测试指南

Faster-RCNN 训练与测试指南 前言 今天我们要来实现一个经典的目标检测模型:Faster-Rcnn。我们使用DAMODEL云平台来实现,这是个很强大的云端平台,功能众多,你可以投你所好去进行你想做的事情。 1. 环境与工具准备 1.1 远程连接…

【漏洞复现】用友 U8CRM getemaildata.php 任意文件读取漏洞

免责声明: 本文内容旨在提供有关特定漏洞或安全漏洞的信息,以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步,并非出于任何恶意目的。阅读者应该明白,在利用本文提到的漏洞信息或进行相关测…

【VMware及CentOS7】安装 配置

一、VMware安装 这里选择的版本是16.1.2,这里不再赘述安装过程,无难点。 crack key: ZF3R0-FHED2-M80TY-8QYGC-NPKYF YF390-0HF8P-M81RQ-2DXQE-M2UT6 ZF71R-DMX85-08DQY-8YMNC-PPHV8 110L3-9135J-M807A-08ARK-84V7L FF31K-AHZD1-H8ETZ-8WWE…

性能监控之Python实战SkyWalking链路追踪

文章目录 一、介绍二、SkyWalking支持的语言三、SkyWalking安装3.1 前提准备3.2 先安装ElasticSearch7.X3.3 Skywalking-OAP 安装3.4 Skywalking-UI 界面安装3.5 访问页面检查SkyWalking是否可以访问 四、Python 项目接入SkyWalking4.1 演示项目代码4.2 验证 sw-python4.3 配置…

【最基础最直观的排序 —— 选择排序算法】

最基础最直观的排序 —— 选择排序算法 选择排序算法是一种简单直观的排序算法。其基本思想是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小&a…