JVM(一)

字节码文件的组成:

基础信息:魔数,字节码文件对应的java版本号,访问表示public final以及父类和接口 

常量池:保存了字符串常量,类或者是接口名,字段名,主要在接口中使用

字段:当前类或者是接口声明的字段信息

方法:当前类或者接口声明的方法信息,字节码指令

属性:指的是类的属性,源码的文件名以及类的列表

字节码文件中常量池的作用:避免相同的内容同时定义节省空间,不仅会使文件变得非常大,况且读取也会非常慢

可以看到字符串的引用存放的是7号的索引,点击常量池的索引,发现又是一个字面量

最后点击25就可以找到最终的字面量了

通过常量池节省字节码文件中的一部分空间,避免同样的数据出现多次

但是为什么字节码文件再进行设计这一块的时候,先通过字符串的引用找到字符串,再来通过字符串找到字面量呢?能不能直接通过字段来找到字面量呢?因为JAVA里面的字符串解析并加载中,需要将String类型加载到字符串常量池中

操作数栈是存放临时数据的地方,两个数相加运算都要放在操作数栈,最终结果都放在操作数栈中,局部变量表是存放方法中局部变量的位置,是在方法中声明的局部变量

下面就是局部变量表,底层是依靠数组来实现的,实际上是依靠你定义变量的顺序来声明数组下标的

istore_i:将操作数栈中的数据取出来放到局部变量表中的对应位置i,那么到底应该放在哪一个位置呢?应该在istrore后面加上一个数组下标,比如说istore_1就会将操作数栈中的内容放到局部变量表中的1号位置,局部变量表中的数据取出来之后,就没了

iload_i:从局部变量表的i位置复制一份取出数放到操作数栈中,最终操作数栈和局部变量表都是会有这个数据的;

iconst_data:将data数据放入操作数栈中

int i=0会拆解出iconst_0和istore_1这两个指令

i_add:将操作数栈中的顶部的两个数据进行相加,并将结果放入到操作数栈中

iinc 1 by 1:将局部变量表中的1号位置加1

JVM是如何执行的?

类加载器:加载class字节玛的内容到内存中

运行时数据区:负责管理JVM使用到的内存,比如说创建对象和销毁对象

方法区:常量,域信息,只有HotSpot虚拟机才有

执行引擎:将字节码文件中的内容解析成机器码,同时使用即时编译优化性能

本地方法接口:调用本地已经编译的方法,比如说虚拟机中已经提供好的C/C++的方法

翻译字节码:针对于字节码的指令进行解释执行

JIT编译器:针对于热点代码进行二次编译(将字节码中的字节码指令编译成机器指令)并将其缓存起来缓存在方法区中

类加载:

1)类加载器子系统负责从文件系统或者是网络中去加载class文件,class文件在文件开头有着特定的文件标识

2)类加载器只是负责class文件的加载,至于它是否可以运行,那么则有执行引擎来决定

3)加载的类信息存放在一块称之为是方法区的内存空间,除了类的信息以外,方法区中还会存放运行时常量池等信息,可能还会包含字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的部分映射)

java虚拟机针对于class文件采用的是按需加载的方式,也就是说当需要使用该类的时候才会将他的class文件加载到内存中生成类对象,而且家在某一个类的class文件的时候,JAVA虚拟机采用的是双亲委派模型,会把请求交给父亲来处理,是一种任务委派模式

在类加载中使用synchronized加锁,向上委托检查,向下加载

1)避免类的重复加载

2)保护程序安全,防止核心API被随意篡改

在JVM中表示两个Class对象是否是同一个需要满足两个条件

1)两个类的完整类名必须完全一致,全限定包名和类名

2)加载这个类的classloader实例对象必须相同

换句话说,在JVM中,即使这两个类对象Class都西昂来源于同一个Class文件,悲痛一个虚拟几所加载,但是只要加载他们的ClassLoader实例对象不同,两个类对象也是不相同的

类加载的相关知识:

类的生命周期描述了一个类加载使用卸载的过程:

加载---链接---初始化----使用----卸载

1)loadding:

a)根据包的全限定包名+类名通过不同的渠道来找到对应的.class文件加载到内存中;

本地的字节码文件+动态代理生成的+网络

b)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,就是将字节码的信息存放到方法区里面,方法区就是用来存放已被加载的类信息,常量,静态变量

c)在方法区中生成这个类的类对象,作为方法区中这个类的各种数据的访问入口

2)链接:

2.1)验证:class文件是以特定的文件符开始的,校验内容是否满足JAVA虚拟机规范;

a)文件格式验证:验证文件是否已特定字符开头,就是以特定的二进制文件开头

b)原信息校验:就是对一些基本信息进行校验,比如说类必须有父类

c)验证程序执行的语义:比如说方法中的指令执行中跳转到不正确的位置

d)符号引用验证:例如说有没有类中访问private修饰的方法

e)版本号检测:如果返回值是true,代表验证成功

class文件的主版本号要大于一个常量,代表所支持的最低版本号,这个常量默认是45代表JDK1.0,JDK的最高版本是52,况且父版本号是0

2.2)准备:为静态变量分配内存并设置初始化值为0值,是默认值的初值,就是防止程序员写出脑残代码,比如说给一个a没有赋初值,如果程序员进行后续操作打印a;

因为final修饰的静态变量,在准备阶段就直接复制初始值了,因为在编译期的时候直接就可以确定值

这里面不会针对于实例变量进行初始化,实例变量会随着对象一起被分配到JAVA的堆里面

2.3)解析:解析所作的操作就是将常量池中的符号引用替换成直接引用

符号引用就是在字节码文件中使用编号来访问字符串常量池中的内容,而直接引用不再使用编号,而是使用内存地址来直接访问具体的数据

3)初始化阶段:执行静态代码块中的代码并且会给静态变量赋初值

其实本质上初始化就是在执行字节码部分的中的clinit部分的字节码指令

iconst:将数字放入到操作数栈中

putstatic:将操作数栈中的数据放到静态变量中

如果将代码进行颠倒,clinit字节码指令执行的顺序和java中编写的顺序是一致的

下面来看一下哪几种方式会导致类的初始化:

1)当访问到一个类的静态变量或者是静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化

2)调用Class.forName(String className)获取到这个类的类对象的时候

3)new一个该类的对象的时候

4)执行Main方法的当前类

添加-XX:+TraceClassLoading参数可以打印出加载并且初始化的类

下面程序的输出结果是:

执行main函数,况且类加载只会执行一次,所以静态代码块也只会执行一次,先进行类加载DACBCB

clinit方法在特定的条件下不会出现,如下面几种情况是不会执行初始化指令的,也就不会生成clinit方法:

1)没有静态代码块况且没有静态变量赋值语句

2)有静态变量的声明但是没有赋值语句,public static int a;

3)静态变量的定义使用final关键字况且这份变量会在准备阶段直接进行初始化

在上面的情况下不会执行初始化操作

1)直接访问父类的静态变量,不会触发到子类的初始化,子类的clinit方法执行前会先执行父类的clinit方法

2)声明一个类以后,内部至少会存在一个这个类的构造器,也就是一定会出现init方法

访问父类的初始化变量只会初始化父类,因为a只是在父类中,此时打印的是a=1

第五步就是为了防止多个线程多次加载同一个类,从下面的代码中而可以看到类加载中的静态代码块只会执行一次,就相当于是一个加锁的过程,一个类在内存中加载一次即可,方法区在JDK1.8使用的是元空间,会使用直接内存缓存起来了,也就是说JAVA虚拟机在执行类加载的时候只会执行一次,只会调用一次clinit()方法

非法的前向引用:当一个定义的变量出现在静态代码块之后,是可以在静态代码块中赋值的,但是是不可以打印这个静态代码块的

 从下到上查找是否加载过,再从上向下进行记载

 

BootStrap:启动类加载器

 rt.jar:包含着java.lang中的String类这样就可以使用BootStrap类加载器来加载自己所扩展的类

1)将自己写的类打包成jar包

2)将自己写的jar包放在任意一个目录:C:/data

3)使用命令来进行扩展,选择添加虚拟机参数

ext目录:通用但是不重要

Appclassloader:在用户自己写的类和第三方依赖jar包的字节码文件

如何打破双亲委派模型? 
 

1)使用PC寄存器存储字节码指令地址有什么用呢?

为什么使用PC寄存器来记录当前线程执行的地址呢?

CPU需要不停的进行切换各个线程,这时候切换回来之后,就得知道下一条从哪里开始继续执行,JVM的字节码解释器就需要通过改变PC寄存器的值来确定下一条该执行啥样的字节码

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring之IoC

Spring的设计理念和整体架构 一句话概括就是:Spring是一个轻量级的、非侵入式的控制反转(IOC)和面向切面(AOP)的框架。 设计理念: 松散耦合: Spring鼓励开发者编写松散耦合的代码,通过依赖注入和接口抽象等方式来减少组件之间的…

DV SSL证书

随着网站越来越多,数据安全显得尤为重要。保护网站安全的数字证书应运而生,各大品牌的SSL证书可以实现网站http到https的转变,加密传输过程,提升品牌形象,优化SEO等优点。SSL证书按照验证等级分为DV,OV&…

意大利航天飞行器公司【Sidereus】完成510万欧元融资

来源:猛兽财经 作者:猛兽财经 猛兽财经获悉,位于意大利萨莱诺的航天飞行器公司Sidereus Space Dynamics今日宣布已完成510万欧元融资。 本轮融资由Primo Space和CDP Venture Capital Sgr领投,通过Italia Venture II - Fondo Impr…

win10 wsl安装步骤

参考&#xff1a; 安装 WSL | Microsoft Learn 一、安装wsl 1.若要查看可通过在线商店下载的可用 Linux 发行版列表&#xff0c;请输入&#xff1a; wsl --list --online 或 wsl -l -o> wsl -l -o 以下是可安装的有效分发的列表。 使用 wsl.exe --install <Distro>…

python结合excel数据轻松实现接口自动化测试

在刚刚进入测试行业的时候&#xff0c;最开始也是做功能测试&#xff0c;我想很多伙伴和我一样&#xff0c;觉得自动化测试都很高端&#xff0c;很神秘。迫不及待的想去学习作自动化测试。 以前比较常用数据库python做自动化&#xff0c;后面发现excel个人觉得更加适合&#x…

Vue开发中Jwt的使用

&#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Vue》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一定基础的程序员&#xff0c;这个专栏…

缓存的力量:提升API性能和可扩展性

缓存是将频繁访问的数据或资源存储在临时存储位置(例如内存或磁盘)的过程&#xff0c;以提高检索速度并减少重复处理的需要。 缓存的好处 提高性能&#xff1a;缓存消除了每次从原始源检索数据的需要&#xff0c;从而提高了响应时间并减少了延迟。减少服务器负载&#xff1a;通…

OrcaTerm AI

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开心好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;…

MySQL(存储过程,store procedure)——存储过程的前世今生 MySQL存储过程体验 MybatisPlus中使用存储过程

前言 SQL&#xff08;Structured Query Language&#xff09;是一种用于管理关系型数据库的标准化语言&#xff0c;它用于定义、操作和管理数据库中的数据。SQL是一种通用的语言&#xff0c;可以用于多种关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;如MySQ…

spark集群环境下,实现人口平均年龄计算

文章目录 任务目标0. 版本信息1. 计算生成renkou.txt2. 文件上传至spark3. 上传文件时&#xff0c;可能出现的常见错误4. 编写spark文件5. 上传集群6. 集群环境下提交任务 任务目标 在虚拟机上部署spark集群&#xff0c;给定renkou.txt文件&#xff0c;输出平均年龄 renkou.t…

linux C++ vscode连接mysql

1.linux使用Ubuntu 2.Ubuntu安装vscode 2.1 安装的是snap版本,直接打开命令行执行 sudo snap install --classic code 3.vscode配置C 3.1 直接在扩展中搜索C安装即可 我安装了C, Chinese, code runner, 安装都是同理 4.安装mysql sudo apt update sudo apt install mysql-…

软件工程与计算总结(七)需求文档化与验证

目录 一.文档化的原因 二.需求文档基础 1.需求文档的交流对象 2.用例文档 3.软件需求规格说明文档 三.需求文档化要点 1.技术文档协作要点 2.需求书写要点 3.软件需求规格说明文档属性要点 四.评审软件需求规格说明文档 1.需求验证与确认 2.评审需求的注意事项 五…

在SIP 语音呼叫中出现单通时要怎么解决?

在VoIP的环境中&#xff0c;特别是基于SIP通信的环境中&#xff0c;我们经常会遇到一些非常常见的问题&#xff0c;例如&#xff0c;单通&#xff0c;注册问题&#xff0c;回声&#xff0c;单通等。这些问题事实上都有非常直接的排查方式和解决办法&#xff0c;用户可以按照一定…

股票价格预测 | Python基于RNN及股票预测实战

循环神经网络(RNN)是基于序列数据(如语言、语音、时间序列)的递归性质而设计的,是一种反馈类型的神经网络,其结构包含环和自重复,因此被称为“循环”。它专门用于处理序列数据,如逐字生成文本或预测时间序列数据(例如股票价格)。 (1)one to one:其实和全连接神经网络…

微信小程序--下拉选择框组件封装,可CV直接使用

一、起因 接到的项目需求,查看ui设计图后,由于微信小程序官方设计的下拉选择框不符合需求,而且常用的第三方库也没有封装类似的,所以选择自己自定义组件。在此记录一下,方便日后复用。 ui设计图如下: 微信官方提供的选择框 对比发现并不能实现我们想要的功能。 二、自定义组件…

video_topic

使用qt5,ffmpeg6.0,opencv&#xff0c;os2来实现。qt并非必要&#xff0c;只是用惯了。 步骤是&#xff1a; 1.读取rtsp码流&#xff0c;转换成mat图像 2.发送ros::mat图像 项目结构如下&#xff1a; videoplayer.h #ifndef VIDEOPLAYER_H #define VIDEOPLAYER_H#include …

企业数字化营销策略如何制定?企业开展数字化营销有的关键步骤?

​制定数字化营销策略是建立数字化营销体系的关键步骤&#xff0c;想要建立好的数字化营销策划&#xff0c;需要企业明确目标客户群体&#xff0c;通过了解他们的需求和行为&#xff0c;来制定相应的营销策略。例如&#xff0c;通过数据分析手段&#xff0c;企业可以确定目标客…

一个tomcat下如何部署多个项目?

1、不修改端口&#xff0c;部署多个项目 清楚tomcat目录结构的应该都知道&#xff0c;项目包是放在webapps目录下的&#xff0c;那能否在同一个tomcat的webapps目录下运行多个不同项目呢&#xff1f; 答案是可以的。 1、将多个项目包放入webapps文件夹下 2、修改conf下的serv…

【师兄啊师兄2】公布,李长寿成功渡劫,敖乙叛变,又一美女登场

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 由玄机制作的师兄啊师兄第一季这才完结没有多久&#xff0c;没想到现在第二季就公布了&#xff0c;连海报和预告都出来了&#xff0c;看样子已经做得差不多了。预告看下来&#xff0c;能够明显感觉到官方又进步…

ad5665r STM32 GD32 IIC驱动设计

本文涉及文档工程代码&#xff0c;下载地址如下 ad5665rSTM32GD32IIC驱动设计,驱动程序在AD公司提供例程上修改得到,IO模拟的方式进行IIC通信资源-CSDN文库 硬件设计 MCU采用STM32或者GD32,GD32基本上和STM32一样,针对ad566r的IIC时序操作是完全相同的. 原理图设计如下 与MC…