JVM解析:class结构和常量及方法初始化

news2024/11/24 5:43:23

文件结构

推荐官方文档:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-3.html

ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];
    u2             fields_count;
    field_info     fields[fields_count];
    u2             methods_count;
    method_info    methods[methods_count];
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

示例

编写一个helloworld类进行编译:

package com.cbry.classs;

public class ClassStruct {
public static void main(String[] args) {
	System.out.println("Hello World");
}
}

在这里插入图片描述

安装HEX插件查看十六进制文件

在这里插入图片描述

magic:魔数

一个魔数对应一个类型的文件,java的class文件的魔数是:cafebabe ,0-3个字节(4个字节:u4)。其它的文件,比如说图片什么的。

00000000 ca fe ba be00 00 00 34 00 22 07 00 02 01 00 1b

00000000 ca fe ba be 00 00 00 34 00 22 07 00 02 01 00 1b

version:版本信息

4-7个字节

minor_version:小版本

major_version:主版本: 00 34 == 52(jdk8)

00000000 ca fe ba be 00 00 00 34 00 22 07 00 02 01 00 1b

常量池

8-9个字节表示常量池长度

00000000 ca fe ba be 00 00 00 34 00 22 07 00 02 01 00 1b

十六进制22 = 十进制34,表示常量池有#1 = #33项,注意**#0项不计入计算**,也没有值。该长度又称为常数计数器,常数计数器-1 = 常量池的项数

常量池第一项

00000000 ca fe ba be 00 00 00 34 00 22 07 00 02 01 00 1b

07表示一个方法信息,后面的 00 0201 00表示方法所属类方法名

常量/方法初始化

常量赋值

当int取值**-1~5时,JVM采用iconst**指令将常量压入栈中。

当int取值**-15**采用iconst指令,取值**-128127采用bipush指令,取值-3276832767**采用sipush指令,取值**-21474836482147483647**采用 ldc 指令。

public class IfClasss {
public static void main(String[] args) {
	int a = 0;
	if (a == 9) {
		a = 6;
	}else {
		a = 8;
	}
}
}

在这里插入图片描述

可以看到先用指令iconst取出数 0 压入操作栈,再istore弹出栈里面的0存放到局部变量表,iload在从局部变量表中取出0压入栈中。

bipush压入9进入操作栈,判断a9即是否09,如果等于,则将0原本所在的局部变量表的位置的数据改成6,然后goto跳转到line 17结束。反之则替换成8。

cinit指令

static int i = 0;
static{
	i = 1;
}

static{
	i = 2;	
}

在这里插入图片描述

编译器会按从上至下的顺序,收集所有static静态代码块和静态成员赋值的代码,合并为一个特殊的方法<cinit>() V

在这里插入图片描述

putstatic指令时给静态变量赋值。

init指令

public class InitClasss {
	private int a = 0;
	
	{
		a = 1;
	}

	public InitClasss(int arg0) {
		this.a = arg0;
	}
	
	public static void main(String[] args) {
		InitClasss ic = new InitClasss(2);
		System.out.println(ic.a);
	}
}

输出结果是三,都是局部变量按顺序执行,new一个对象,先执行类里面的逻辑再执行构造函数。 a的值的变化是:0 -> 1-> 2 。

具体是执行main函数,然后new的时候构造类对象,然后进行a的值变化,传参。

main方法是一个特殊的方法,在程序开始运行时,系统会找到main方法所在的那个class文件,然后把main方法的代码装入内存,从main的第一条语句开始执行,直到main的最后一条语句结束。至于main所在的类不用管它,它在main装入内存时不起作用的,只有创建这个类的对象时才起作用,也就是使用new的时候。

在这里插入图片描述

在这里插入图片描述

aload_0把this装载到了操作数栈中aload_0是一组格式为aload_的操作码中的一个,这一组操作码把对象的引用装载到操作数栈中标志了待处理的局部变量表中的位置,但取值仅可为0、1、2或者3。

iload_、lload_、fload_和dload_,这里的i代表int型,l代表long型,f代表float型以及d代表double型。

iload_0、iload_1、aload_0之类的数字代表的时局部变量表中的Slot槽位中的数据。

  						0: aload_0	//相当于把this放到操作数栈
  			
  				​		1: invokespecial #10                 // Method java/lang/Object."<init>":()V        //调用父类Object的构造方法
  				​		4: aload_0	//相当于把this放到操作数栈
  				​         5: iconst_0 	//将常数0压入操作栈
  				​         6: putfield      #13                 // Field a:I	//常数池中的13项:a属性:this.a,到这里就是将0赋值给了this.a
  				​         9: aload_0
  				​        10: iconst_1
  				​        11: putfield      #13                 // Field a:I  ,	即this.a = 1
  				​        14: aload_0
  				​        15: iload_1	//将slot_1中的传参3从局部变量表放入操作数
  				​        16: putfield      #13                 // Field a:I
  				​        19: return

方法

public class MethodClasss {
	//空构造方法
	public MethodClasss() {}
	
	private void method1() {}
	
	public final void method2() {}
	
	public void method3() {}
	
	private static void method4() {}
	
	public static void main(String[] args) {
		MethodClasss mc = new MethodClasss();
		mc.method1();
		mc.method2();
		mc.method3();
		mc.method4();
		MethodClasss.method4();
	}
	
}

在这里插入图片描述

可以看到private和static修饰的方法时是invokespecial和invokestatic方法(private final也是),而public修饰的则是invokevirtual方法。因为public的方法不能被唯一确认,需要运行时确定。而其它的special方法和static则是静态绑定,直接找到确定。

     0: new           #1                  // class com/cbry/classs/MethodClasss
     3: dup
     4: invokespecial #20                 // Method "<init>":()V
     7: astore_1
     8: aload_1
     9: invokespecial #21                 // Method method1:()V
     12: aload_1
     13: invokevirtual #23                 // Method method2:()V
     16: aload_1
     17: invokevirtual #25                 // Method method3:()V
     20: invokestatic  #27                 // Method method4:()V
     23: invokestatic  #27                 // Method method4:()V

这里的new分两部分:1、分配对象内存;2、将对象的引用压入操作栈;

dup则是复制一份对象的引用在这里插入图片描述
在栈顶,这个复制的部分是为了给构造函数操作,两个引用指向一个分配的对象内存空间。操作完(构造函数)操作后,复制的引用弹出,栈里面还有一个引用(他指向的对象已经被构造了)。

然后就是引用不断的在局部变量表(astore)和操作栈(aload)中使用—调用执行方法。其中static因为是静态方法不需要对象的调用,即不需要store和load操作。

多态原理

在这里插入图片描述

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

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

相关文章

通过python的signal库模拟电源设备的csine波形

import numpy as np import matplotlib.pyplot as plt import random from scipy import signal def csin(length, amp,lenf,n):"""生成模拟CSIN波形的函数:param length: 波形长度:param amp: 波形振幅:return: CSIN波形数据"""amp 100 if (am…

函数和控制流

专栏简介&#xff1a;本专栏作为Rust语言的入门级的文章&#xff0c;目的是为了分享关于Rust语言的编程技巧和知识。对于Rust语言&#xff0c;虽然历史没有C、和python历史悠远&#xff0c;但是它的优点可以说是非常的多&#xff0c;既继承了C运行速度&#xff0c;还拥有了Java…

基于Springboot的宠物店管理系统(源代码+数据库)087

基于Springboot的宠物店管理系统(源代码数据库)087 一、系统介绍 本系统分为管理员、店员两种角色 店员角色包含以下功能&#xff1a; 登录、宠物主人管理、宠物管理、宠物医疗管理、宠物销售管理、宠物寄养管理、宠物用品管理、宠物日常服务管理、宠物常见问题、个人中心、…

基于JavaSwing+MySQL的仓库商品管理系统

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88046204?spm1001.2014.3001.5503 JDK1.8 MySQL5.7 功能&#xff1a;管理员与员工两个角色登录&#xff0c;增删改查用户信息&#xff0c;修改密码&#xff0c;增删改查商品信息&#xff0c…

Java文件与IO

文章目录 前言认识文件绝对路径与相对路径普通文件与二进制文件 Java中的操作文件File 类文件的读写 前言认识文件 狭义上的文件(file)。针对硬盘这种持久化存储的I/O设备&#xff0c;当我们想要进行数据保存时&#xff0c;往往不是保存成一个整体&#xff0c;而是独立成一个个…

RocketMQ基础概念

目录 1.简介 2.架构 3.核心概念 1.简介 RocketMQ 是一款开源的分布式消息中间件&#xff0c;最初由阿里巴巴集团开发并开源。它旨在为分布式系统提供可靠、高性能、可扩展的消息通信能力。RocketMQ和RabbitMQ、KAFKA一起并列为现在主流的三大消息中间件。 一般MQ可以从三个…

Python(八)字符编码

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

06_HDMI 显示器驱动设计与验证

06_HDMI 显示器驱动设计与验证 1. HDMI 接口及引脚定义1.1 HDMI A Type 接口引脚图1.2 HDMI A Type 接口引脚定义 2. HDMI 原理2.1 HDMI 显示原理2.2 TMDS 传输原理 3. 实验目标4. 程序框图4.1 顶层模块4.2 时钟生成模块4.3 HDMI 驱动控制模块4.3.1 第一个步骤4.3.2 编码模块参…

反垄断在中国

中国通过反垄断法 中国通过了具有里程碑意义的反托拉斯立法,外国企业表示谨慎性的欢迎,希望该法案能带来更大的开放性,但需要观察它是如何实施的。(华尔街日报 2007年8月32日报道) 反垄断法禁止垄断协议和诸如卡特尔及价格操纵,但允许能促进创新和技术进步的垄断之存在。…

微软亚洲研究院推出AI编译器界“工业重金属四部曲”

编者按&#xff1a;编译器在传统计算科学中一直是一个重要的研究课题。在人工智能技术快速发展和广泛应用的今天&#xff0c;人工智能模型需要部署在多样化的计算机硬件架构上。同时&#xff0c;训练和部署大型人工智能模型时又对硬件性能有着更高的要求&#xff0c;有时还需根…

c#示例-json序列化和json树

序列化 由于指针和引用类型的存在&#xff0c;在运行中的程序中&#xff0c;数据不一定是整块的。 可能东一块西一块散落在内存的各个地方。 序列&#xff0c;是指连续且有序的一个整体。序列化就是把数据变为连续有序整体的过程。 经过这样处理后的数据就可以方便的进行传输…

1130 - Host XXX‘ is not allowed to connect to this MySQL server

mysql 连接报错 这个问题是因为在数据库服务器中的mysql数据库中的user的表中没有没有用户 解决的方法&#xff1a; 登入mysql后&#xff0c;更改 “mysql” 数据库里的 “user” 表里的 “host” 项&#xff0c;从”localhost”改称’%’。 1、连接服务器: mysql -u root -p…

万字解读 | 数据可视化平台--FineBI

什么是BI 学习目标 知道什么是BI 知道FineBI的优势 1. 商业智能: BI&#xff08;Business Intelligence&#xff09;是指通过收集、分析和解释企业内外部数据&#xff0c;为企业决策提供支持和指导的一种技术和工具。商业智能的目标是帮助企业管理者和决策者更好地理解企业…

vivado 添加 pynq-z2板

以vivado2019.02版本为例 1下载地址 https://www.tulembedded.com/FPGA/ProductsPYNQ-Z2.html 2.点击下载 3.解压添加 注&#xff1a;如果没有board_files 可以自己创建一个 4.重新打开vivado

跨境电商企业实施WMS仓储管理系统有什么要注意的

在跨境电商行业中&#xff0c;仓储管理是关键的环节之一。为了提高仓储效率和准确性&#xff0c;许多跨境电商企业选择实施WMS仓储管理系统解决方案。然而&#xff0c;实施电商企业WMS系统并不是一项简单的任务&#xff0c;需要注意一些关键要点。本文将介绍跨境电商企业实施WM…

Ubuntu 18.04 Docker 安装配置 Apollo 6.0

百度 Apollo 安装测试&#xff08;1&#xff09; Apollo 6.0 安装完全指南 在这一步出错&#xff1a; 进入到 Apollo 源码根目录&#xff0c;打开终端&#xff0c;执行下述命令以启动 Apollo Docker 开发容器 ./docker/scripts/dev_start.sh并没有成功启动 Apollo docker 开发…

科技成果鉴定报告的重要性

科技成果鉴定是评估科技成果价值、可行性和科学性的过程&#xff0c;鉴定结果直接关系到科技成果的应用和推广。科技成果鉴定报告是鉴定结果的呈现和总结&#xff0c;对于科技成果的评估和利用具有重要的价值和意义。 1、科技成果价值评估&#xff1a;在科技创新和技术发展中…

在VMware Workstation安装 ESXI8.0初体验

文章目录 &#x1f41f;前言&#x1f41f;安装&#x1f41f;在VMware WorkStation中创建虚拟机&#x1f41f;ESXI部署安装&#x1f41f;安装完成后配置 &#x1f41f;前言 ESXI8.0版本开始最低RAM从以前的4GB变为8GB 本文所使用到的镜像以及Key都可以到我的网站中下载 地址&…

数学分析:k维曲面

这部分比较抽象&#xff0c;我就不按照书本上的定义来了&#xff0c;直接讲直观的理解。 一般来说&#xff0c;我们认为&#xff1a; 这是一个圆&#xff0c; 但同时也可以认为他是一个一维的曲面。 同理 是一个球面 但同时也是一个二维的曲面&#xff0c;依次类推。 我们…

AWS 云区域(region),可用区(AZ)

AWS 提供三种地理性组件&#xff1a; Regions&#xff1a;区域&#xff0c;即AWS提供云服务的一个区域&#xff0c;其目的是为了用户能就近接入&#xff0c;降低网络延迟。通常是一个城市的若干个AZ组成一个region。2016年&#xff0c;AWS 宣布在其全球region之间建设了100GbE…