java(JVM)

JVM

Java的JVM(Java虚拟机)是运行Java程序的关键部件。它不直接理解或执行Java源代码,而是与Java编译器生成的字节码(Bytecode)进行交互。下面是对Java JVM更详尽的解释:

1.字节码

当你使用Java编译器(javac)编译Java源代码时,会生成一种中间语言——字节码(.class文件)。字节码是一种平台无关的代码格式,设计目的是为了实现跨平台的兼容性。

字节码(Bytecode)是一种介于高级编程语言和机器语言之间的低级程序表示形式。它是许多编程语言(如Java、Python等)在编译或解释执行过程中产生的中间代码。字节码的主要特点和作用包括:

  1. 平台无关性:字节码不针对任何特定的硬件架构,它是一种抽象的、与具体处理器无关的指令集。这使得编译后的字节码可以在任何支持该字节码格式的平台上运行,实现了“一次编写,到处运行”的跨平台特性。

  2. 简化编译过程:相比直接生成机器语言,产生字节码的过程更为简单,因为字节码的指令集通常比机器语言指令集更小、更通用。

  3. 安全性增强:在执行字节码前,虚拟机(如Java虚拟机JVM)可以对其进行验证,确保代码的安全性,比如检查类型安全,防止非法访问内存等。

  4. 优化机会:JVM或其他虚拟机可以在运行时对字节码进行动态优化,如即时编译(JIT),将频繁执行的字节码转换为更高效的本地机器码,提高程序执行效率。

  5. 易于分析与变换:由于字节码的结构较为简单且有明确的规范,工具和框架可以更容易地对其进行分析、修改或转换,这对于代码混淆、程序分析、动态代理等技术尤为重要。

例如,在Java中,源代码被编译成.class文件中的字节码,这些字节码随后由Java虚拟机(JVM)解释或即时编译成机器码执行。这一层抽象极大地增强了Java程序的可移植性和安全性。

2.加载与验证

当一个Java程序开始运行时,JVM负责加载所需的字节码文件。加载后,JVM会对这些字节码进行验证,确保它们没有违反Java的安全规范,如类型安全等。

Java 虚拟机(JVM)的类加载过程主要包括五个阶段:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)和初始化(Initialization)。下面是对加载与验证阶段的详细介绍:

加载(Loading)

  1. 寻找并加载类的二进制数据:JVM查找并读取类的字节码文件(通常是.class文件),这个过程可以通过不同的类加载器来完成,包括启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)、系统类加载器(Application ClassLoader)或自定义类加载器。

  2. 创建java.lang.Class实例:JVM为每个加载的类创建一个对应的Class对象,作为方法区中类数据的访问入口。这个对象封装了类的各种信息,如类名、父类、实现的接口、常量池、字段、方法等。

验证(Verification)

验证阶段是确保加载的字节码是否符合JVM规范要求,防止恶意代码损害系统安全。验证过程分为四个主要步骤:

3.文件格式验证

检查.class文件的格式是否正确,包括魔数(Magic Number)、版本号、常量池等,确保文件结构合法。

Java虚拟机(JVM)的文件格式验证是类加载验证过程的第一个阶段,旨在确保.class文件的格式遵守Java Class File Format规范,确保字节码文件的基本结构正确无误,可以被正确解析。此阶段的验证内容主要包括以下几个方面:

  1. 魔数验证(Magic Number Verification):每个.class文件的开头都有一个特殊的4字节序列(十六进制表示为CAFEBABE),被称为魔数。验证器首先检查文件头的魔数是否正确,以此确认文件是否为有效的Java字节码文件。

  2. 版本信息验证:接下来验证.class文件的版本号,包括主版本号和次版本号,确保其与当前JVM的版本兼容。如果不兼容,JVM将拒绝加载该类。

  3. 常量池计数和验证:验证常量池的数量是否与文件中声明的一致,并对常量池中的每一项(如类名、字符串、数字、方法引用等)进行基本的格式验证,确保它们的类型和结构正确。

  4. 访问标志验证:检查类或接口的访问修饰符是否合法,例如确保一个类不能同时被声明为abstractfinal

  5. 类索引、父类索引和接口计数验证:确保类索引指向的常量池项确实代表一个有效的类,父类索引(对于非java.lang.Object的类)指向的是一个有效的超类,接口计数正确无误,且所有接口引用有效。

  6. 字段表和方法表验证:验证类的字段和方法数量是否与声明相符,以及字段和方法的描述符是否合法,包括返回类型、参数类型等。

  7. 属性表验证:检查类、字段和方法的属性表,确保属性的数量、类型和长度正确,特别是对Code属性(包含方法的字节码)的初步检查,以确保其格式合理。

文件格式验证主要是对.class文件的结构进行检查,确保其基本的格式和一致性,是整个类加载验证流程的基础。如果这一阶段检测到任何错误,类加载过程就会终止,并抛出相关错误信息。

4.元数据验证

校验类的元数据信息,如检查类是否有父类(除了java.lang.Object外)、检查final类是否被继承、检查方法的重写是否遵循规则等。

Java虚拟机(JVM)的元数据验证是类加载验证过程的第二个阶段,紧随文件格式验证之后。这一阶段主要关注类结构的语义检查,确保类的元数据信息(如类、接口、字段、方法等)遵循Java语言规范,不会引入逻辑上的冲突或不一致性。元数据验证的具体内容包括但不限于以下几个方面:

  1. 类结构验证:确保类的继承关系合法,例如一个类只能有一个直接父类(除了java.lang.Object外),接口不能有父类,类不能直接或间接实现自己,也不能直接或间接扩展自己。

  2. 字段和方法重载验证:检查类中的字段和方法名称是否唯一(考虑重载的情况下),以及它们的访问权限、修饰符(如staticfinalprivate等)是否合法。

  3. final类和方法验证:确保声明为final的类没有子类,final的方法没有被子类重写。

  4. 抽象类和方法验证:如果一个类声明为抽象类,验证它是否有子类;如果一个方法声明为抽象方法,确保它在非抽象类中不被实现。

  5. 接口验证:确保接口不包含实例字段(除了static final),所有方法都是抽象的(Java 8之后允许默认方法和静态方法),接口不能继承自非接口类型。

  6. 常量池中的符号引用验证:虽然符号引用的完全解析发生在解析阶段,但在元数据验证期间也会对常量池中的某些符号引用进行基本的格式检查,确保它们指向的描述符(如类、方法、字段的描述符)语法上是正确的。

元数据验证是确保类定义逻辑正确性的关键步骤,它帮助JVM识别那些在文件格式上看似正确但实际上违反了Java语言规范的类。通过这一系列严格的检查,JVM能够排除那些在类结构上有潜在问题的类,从而提升系统的稳定性和安全性。

5.字节码验证

这是最复杂的一个阶段,通过数据流分析和控制流分析等手段,确保字节码的语义是合法的,不会引起 JVM 执行时的异常,比如类型转换错误、跳转指令的合法性等。

Java虚拟机(JVM)的字节码验证是类加载验证过程中的第三个阶段,也是最为复杂和关键的一个环节。这一阶段的目标是确保字节码的语义正确性,防止非法或有害的操作,保证程序执行的安全性。字节码验证主要关注以下几个方面:

  1. 类型安全验证:这是字节码验证的核心部分,涉及数据流分析和控制流分析。它检查每个操作码(opcode)对操作数栈和局部变量表的操作是否类型安全,确保不会发生类型不匹配的错误,比如错误的类型转换、非法的运算操作等。例如,确保加法操作的两个操作数都是数值类型,且类型兼容。

  2. 控制流验证:分析字节码的控制流图,确保程序的控制流逻辑是合理的,没有死循环,也不会跳转到不存在的指令或非法的代码段。此外,还检查异常处理表的正确性,确保try-catch块的范围合理且捕获的异常类型与抛出的异常匹配。

  3. 操作数栈和局部变量表的平衡性验证:确保每个方法的执行过程中,操作数栈和局部变量表的使用前后保持平衡,即每条指令执行前后栈深度和局部变量的使用状态符合预期,不会出现栈溢出或下溢的情况。

  4. 方法体验证:详细检查方法内部的代码,包括对方法的Code属性中的字节码指令序列进行验证,确保指令的顺序、分支、跳转逻辑正确,以及对方法返回类型和异常处理的合规性检查。

  5. 对常量池引用的额外验证:在这一阶段,虽然大部分符号引用的解析发生在解析阶段,但对于直接涉及到的常量池条目(如方法调用、字段访问等),会进一步验证这些引用的有效性和类型兼容性。

字节码验证是JVM安全机制的重要组成部分,通过严格的逻辑检查,可以有效防止恶意代码利用字节码层面的漏洞进行攻击,保证了Java程序的健壮性和安全性。尽管这一过程相对耗时,但它对维护Java“一次编写,到处运行”的承诺至关重要。

6.符号引用验证

在解析之前对类自身以外的信息(如常量池中的类、方法、字段符号引用)进行校验,确保可以成功解析到对应的类、方法或字段。

符号引用验证是Java虚拟机(JVM)类加载验证过程中的第四个阶段,发生在解析之前。这一阶段主要关注常量池中的符号引用(Symbolic References),确保这些引用在实际解析时能够成功定位到目标类、字段或方法。符号引用验证包括以下几个方面:

  1. 有效性验证:检查常量池中的符号引用是否格式正确,比如类或接口的全限定名、字段的名称和描述符、方法的名称、描述符及参数类型等,确保这些信息符合Java语言规范。

  2. 可访问性验证:确保当前类对符号引用所指的目标具有合法的访问权限。例如,私有(private)成员不能被外部类访问,包外的类不能访问包内未声明为public的成员等。

  3. 存在性验证:验证被引用的类、字段、方法是否真实存在。虽然这一步骤在实际解析时会更加彻底,但在符号引用验证阶段也会进行初步检查,避免明显的无效引用。

  4. 类型兼容性验证:对于方法调用和字段访问,检查调用者和被调用者之间是否存在兼容性问题,比如方法的参数类型、返回类型与预期是否一致,字段类型是否兼容等。

  5. 接口合法性验证:如果符号引用指向的是接口方法或接口本身,确保符合Java接口的使用规则,比如类实现接口的所有抽象方法,或者接口不能继承自非接口等。

符号引用验证的目的在于提前发现潜在的引用错误,减少在解析阶段因引用问题导致的失败,从而提高类加载的效率和稳定性。虽然解析阶段会进一步验证和具体化这些符号引用,但前期的符号引用验证依然是必要的,它作为一道安全网,有助于维护Java程序的健壮性。

验证阶段是非常重要的,它确保了类文件的格式正确、语义合法,是JVM安全机制的重要组成部分。如果在验证阶段发现错误,JVM将抛出相关异常,阻止有问题的类被加载到内存中执行。

  1. 解释与即时编译(JIT):早期的JVM通过逐行解释字节码来执行程序,这种方式效率较低。现代JVM大多采用即时编译技术(Just-In-Time Compilation),即在运行时将频繁执行的字节码编译为对应平台的本地机器码,从而显著提升执行效率。

  2. 内存管理:JVM自动管理程序运行时的内存分配和回收。它将内存划分为不同的区域,如堆(Heap)用于存储对象实例,栈(Stack)用于方法调用和局部变量,以及方法区(Method Area)用于存储类的元数据等。垃圾收集器(Garbage Collector, GC)是JVM的一部分,负责自动回收不再使用的内存空间,减少程序员手动管理内存的工作。

  3. 多线程支持:JVM内置了对多线程的支持,使得Java程序可以轻松创建和管理多个线程。JVM负责调度线程、管理线程生命周期,并提供了一套内存模型来保证线程间的通信正确性。

  4. 安全性:JVM通过字节码验证、安全沙箱(限制了程序访问本地系统资源的能力)、类加载器体系结构等多种机制来保障Java程序的执行安全。

正因为有了JVM,Java程序员编写的代码可以在任何安装了JVM的硬件和操作系统上运行,无需重新编译,实现了高度的可移植性和跨平台能力。

GC算法(垃圾回收算法)

Java虚拟机中的垃圾回收算法主要有以下几种:

  1. 标记-清除(Mark and Sweep)

    • 这是最基础的垃圾回收算法。首先遍历所有可达的对象并做上标记,然后再次遍历堆内存,未被标记的对象被视为垃圾并回收其空间。
    • 缺点是会产生内存碎片,导致后续分配大对象时可能无法找到足够的连续空间。
  2. 复制(Copying)

    • 将内存分为两个相等的区域,每次只使用其中一个区域。当这一区域满时,将存活对象复制到另一个区域,然后清空之前使用的区域。
    • 这种方法简单高效,能解决内存碎片问题,但代价是内存使用率只有50%。
  3. 标记-整理(Mark and Compact)

    • 结合了标记-清除和复制的优点,首先标记出所有活动对象,然后将存活的对象向一端移动,最后清理掉边界外的内存空间。
    • 这个过程既解决了碎片问题,又不需要两倍的内存空间。
  4. 分代收集(Generational Collection)

    • 基于“大多数对象都是朝生夕灭”的假设,将堆内存分为新生代和老年代。
    • 新生代通常使用复制算法,因为它频繁GC但每次回收的大多是短命对象。
    • 老年代则常用标记-清除或标记-整理算法,因为这里的对象生命周期长,回收频率低。

垃圾回收器

JVM提供了多种垃圾回收器,它们实现了上述算法的不同组合,以适应不同场景的需求。以下是一些常见的垃圾回收器:

  1. Serial GC:适用于单CPU环境,新生代和老年代都采用串行回收的方式,简单高效但无法充分利用多核处理器的优势。

  2. Parallel GC(也称为Throughput Collector):在多CPU环境中并行进行垃圾回收,提高吞吐量,但可能会引起较长的暂停时间。

  3. Concurrent Mark and Sweep (CMS) GC:老年代垃圾回收器,目标是减少停顿时间,大部分工作与用户线程并发执行,但在极端情况下可能会出现“ Concurrent Mode Failure”。

  4. G1(Garbage First)GC:设计用于大型堆的服务器应用,它将堆内存划分为多个大小相等的区域(Region),并采用分代收集策略,同时努力达到低延迟和高吞吐量的目标。

类加载机制

Java的类加载机制主要包括以下步骤:

  1. 加载(Loading):查找并加载类的二进制数据,通常是.class文件。

  2. 验证(Verification):检查加载的类是否有正确的内部结构,并符合Java语言规范。

  3. 准备(Preparation):为类的静态变量分配内存,并将其初始化为默认值。

  4. 解析(Resolution):将常量池中的符号引用转换为直接引用的过程,如果需要的话。

  5. 初始化(Initialization):执行类的静态初始化代码,给静态变量赋予程序员设定的初始值。

类加载器分为四种主要类型:Bootstrap ClassLoader、Extension ClassLoader、Application ClassLoader 和 Custom ClassLoader(用户自定义)。它们形成了一个层次结构,负责加载不同来源的类,且遵循双亲委派模型原则,即类加载请求先委托给父加载器处理,如果父加载器不能处理再由自己尝试加载。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SolidWorks对设计电脑硬件配置要求是怎么样的

SolidWorks,作为达索系统(Dassault Systemes)旗下的子公司,一直以其出色的机械设计软件解决方案而著称。它是基于Parasolid内核开发,是单核三维设计软件,面上使用比较多的版本有SolidWorks2022、SolidWorks…

13大最佳工程项目管理系统软件盘点

国内外主流的13款工程项目管理系统软件:Worktile、中建软件、泛微建筑项目管理软件、LiquidPlanner、Wrike、建文软件、广联达、Microsoft Project、泛普软件、Procore、Buildertrend、Fieldwire、Autodesk Construction Cloud。 在快速变化的工程领域,有…

java采集微信公众号数据

需求背景: 最新需要调用微信公众号api 去微信公众号采集 发布文章数据。 (本片文章的意义:根据自己开发的方案来提供思路,当然那不会提供代码。代码是最没有 含金量的东西。) 1:遇到的坑:首先 想到的是调用 https://api.weixin…

github 本地仓库上传及报错处理

一.本地文件上传 这里为上传部分,关于gitbash安装配置,读者可自行搜索,由于已经安装完成,未进行截图保存,这里便不做赘述。 1.登录git账号并创建一个仓库 点击仓库打开后会看到这个仓库的网址链接(这个链…

Mac安装jadx并配置环境

jadx官网:GitHub - skylot/jadx: Dex to Java decompiler 第一种: 安装jadx命令: brew install jadx 启动jadx-gui命令: jadx-gui 可能遇到的问题: Downloading https://formulae.brew.sh/api/formula.jws.json** h…

Python-程序流程控制

目录 1. 分支语句 1.1 if 1.2 if-else 1.3 if-elif-else 2. 循环语句 2.1 while 2.2 for 3.跳转语句 3.1 break 3.2 continue 1. 分支语句 1.1 if aint(input("请输入成绩")) if a>100:print ("牛逼") if a<60:print("不牛逼")1.2 if-e…

《软件定义安全》之八:软件定义安全案例

第8章 软件定义安全案例 1.国外案例 1.1 Fortinet&#xff1a;传统安全公司的软件定义方案 Fortinet的软件定义安全架构强调与数据中心的结合&#xff0c;旨在将安全转型为软件定义的模式&#xff0c;使安全运维能够与数据中心的其他部分一样灵活、弹性。在Fortinet看来&…

【最新鸿蒙应开发】——HarmonyOS沙箱目录

鸿蒙应用沙箱目录 1. 应用沙箱概念 应用沙箱是一种以安全防护为目的的隔离机制&#xff0c;避免数据受到恶意路径穿越访问。在这种沙箱的保护机制下&#xff0c;应用可见的目录范围即为应用沙箱目录。 对于每个应用&#xff0c;系统会在内部存储空间映射出一个专属的应用沙箱…

使用神卓互联来访问单位内部web【内网穿透神器】

在现代工作环境中&#xff0c;有时我们需要从外部访问单位内部的 web 资源&#xff0c;而神卓互联这款内网穿透神器就能完美地满足这一需求。 使用神卓互联来访问单位内部 web 其实并不复杂&#xff0c;以下是大致的使用步骤和配置方法。 首先&#xff0c;我们需要在单位内部的…

pointnet

train_classification.py 把第91行修改为自己的路径&#xff0c;就可以运行了 test_cla.py&#xff0c;需要训练完才能运行测试&#xff0c;我没训练完&#xff0c;所以报错显示我没有best.pth文件 网盘里面是我运行的训练和测试的视频&#xff0c;以及源代码&#xff0c;数…

YOLOv10在RK3588上的测试(进行中...)

1.代码源 国内镜像站在gitcode。这个镜像站也基本上包含了github上常用项目的镜像。然后它的主发布源在这里&#xff1a; GitCode - 全球开发者的开源社区,开源代码托管平台 yolov10是清华主导做的... 然后&#xff0c;在维护列表里看到了这个&#xff1a; 2024年05月31日&am…

【深度优先搜索 广度优先搜索】297. 二叉树的序列化与反序列化

本文涉及知识点 深度优先搜索 广度优先搜索 深度优先搜索汇总 图论知识汇总 LeetCode297. 二叉树的序列化与反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作&#xff0c;进而可以将转换后的数据存储在一个文件或者内存中&#xff0c;同时也可以通过网络传…

Day 16:3040. 相同分数的最大操作数目II

Leetcode 相同分数的最大操作数目II 给你一个整数数组 nums &#xff0c;如果 nums 至少 包含 2 个元素&#xff0c;你可以执行以下操作中的 任意 一个&#xff1a; 选择 nums 中最前面两个元素并且删除它们。选择 nums 中最后两个元素并且删除它们。选择 nums 中第一个和最后一…

1058 选择题(测试点1)

solution 把题目设置为结构体&#xff0c;记录题目的总分&#xff0c;做错该题的人数&#xff0c;题目编号&#xff08;从1开始&#xff09;&#xff0c;正确答案。对于输入的学生答案提取每道题的回答&#xff0c;与答案对比是否相等&#xff0c;若相等则该同学的分数加上这一…

PHP和Mysql前后端交互效果实现

一、连接数据库基本函数 mysqli_connect(); 作用&#xff1a;创建数据库连接&#xff0c;打开一个新的mysql的连接。传参顺序&#xff1a;数据库地址、数据库账号、数据库密码 <?phpecho mysqli_connect("localhost",root,root) ?> /*结果&#xff1a;F…

Cloudflare 错误 1006、1007、1008 解决方案 | 如何修复

根据不完全统计&#xff0c;使用 Cloudflare 的网站比例已经接近 20%。因此&#xff0c;在日常工作中&#xff0c;比如进行网页抓取时&#xff0c;您可能经常会遇到一些因 Cloudflare 而产生的困难。例如&#xff0c;遇到 Cloudflare 错误 1006、1007 和 1008&#xff0c;这些错…

通过Stream流对集合进行操作

Stream Api是JDK8提供的新特性&#xff0c;可以更为方便地对集合进行操作&#xff0c;比如我今天遇到的一个场景&#xff1a; 将本地的一个视频文件分成多块上传到Minio服务器&#xff0c;现在上传功能已经完成&#xff0c;需要调用minioClient对已经上传的文件重新合并成一个新…

for循环结构

循环&#xff1a; 循环是一个重复执行一个代码的结构。只要满足循环的条件&#xff0c;会一直执行这个代码。 循环条件&#xff1a;在一定范围之内&#xff0c;按照指定的次数来执行循环。 循环体&#xff1a;在指定的次数内&#xff0c;执行的命令序列。只要条件满足&#…

C# 设置PDF表单不可编辑、或提取PDF表单数据

PDF表单是PDF中的可编辑区域&#xff0c;允许用户填写指定信息。当表单填写完成后&#xff0c;有时候我们可能需要将其设置为不可编辑&#xff0c;以保护表单内容的完整性和可靠性。或者需要从PDF表单中提取数据以便后续处理或分析。 之前文章详细介绍过如何使用免费Spire.PDF…

怎么改图片尺寸更方便?在线图片改大小的使用方法

图片怎么快速改尺寸呢&#xff1f;在网上传图或者做其他用途时&#xff0c;经常会对图片的尺寸有要求&#xff0c;当拍摄或者制作的图片太大或者太小时&#xff0c;都会导致图片的无法正常使用&#xff0c;那么就需要按照规定将图片改大小之后才能正常使用。 在遇到图片修改大…