jvm类文件结构

一 概述

在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。

Clojure(Lisp 语言的一种方言)、Groovy、Scala 等语言都是运行在 Java 虚拟机之上。下图展示了不同的语言被不同的编译器编译成.class文件最终运行在 Java 虚拟机之上。.class文件的二进制格式可以使用 WinHex 查看。

可以说.class文件是不同的语言在 Java 虚拟机之间的重要桥梁,同时也是支持 Java 跨平台很重要的一个原因。

二 Class 文件结构总结

根据 Java 虚拟机规范,类文件由单个 ClassFile 结构组成:

`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];
}` 

![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)



下面详细介绍一下 Class 文件结构涉及到的一些组件。

Class文件字节码结构组织示意图 (之前在网上保存的,非常不错,原出处不明):

2.1 魔数

    u4             magic; 

每个 Class 文件的头四个字节称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接收的 Class 文件

程序设计者很多时候都喜欢用一些特殊的数字表示固定的文件类型或者其它特殊的含义。

2.2 Class 文件版本

    u2             minor_version;
    u2             major_version;

紧接着魔数的四个字节存储的是 Class 文件的版本号:第五和第六是次版本号,第七和第八是主版本号

高版本的 Java 虚拟机可以执行低版本编译器生成的 Class 文件,但是低版本的 Java 虚拟机不能执行高版本编译器生成的 Class 文件。所以,我们在实际开发的时候要确保开发的的 JDK 版本和生产环境的 JDK 版本保持一致。

2.3 常量池

    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];

紧接着主次版本号之后的是常量池,常量池的数量是 constant_pool_count-1(常量池计数器是从1开始计数的,将第0项常量空出来是有特殊考虑的,索引值为0代表“不引用任何一个常量池项”)。

常量池主要存放两大常量:字面量和符号引用。字面量比较接近于 Java 语言层面的的常量概念,如文本字符串、声明为 final 的常量值等。而符号引用则属于编译原理方面的概念。包括下面三类常量:

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法的名称和描述符

常量池中每一项常量都是一个表,这14种表有一个共同的特点:开始的第一位是一个 u1 类型的标志位 -tag 来标识常量的类型,代表当前这个常量属于哪种常量类型.

类型标志(tag)描述
CONSTANT_utf8_info1UTF-8编码的字符串
CONSTANT_Integer_info3整形字面量
CONSTANT_Float_info4浮点型字面量
CONSTANT_Long_info长整型字面量
CONSTANT_Double_info双精度浮点型字面量
CONSTANT_Class_info类或接口的符号引用
CONSTANT_String_info字符串类型字面量
CONSTANT_Fieldref_info字段的符号引用
CONSTANT_Methodref_info10类中方法的符号引用
CONSTANT_InterfaceMethodref_info11接口中方法的符号引用
CONSTANT_NameAndType_info12字段或方法的符号引用
CONSTANT_MothodType_info16标志方法类型
CONSTANT_MethodHandle_info15表示方法句柄
CONSTANT_InvokeDynamic_info18表示一个动态方法调用点

.class 文件可以通过javap -v class类名 指令来看一下其常量池中的信息(javap -v class类名-> temp.txt :将结果输出到 temp.txt 文件)。

2.4 访问标志

在常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口,是否为 public 或者 abstract 类型,如果是类的话是否声明为 final 等等。

类访问和属性修饰符:

我们定义了一个 Employee 类

package top.snailclimb.bean;
public class Employee {
   ...
}

通过javap -v class类名 指令来看一下类的访问标志。

2.5 当前类索引,父类索引与接口索引集合

    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];

类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,由于 Java 语言的单继承,所以父类索引只有一个,除了 java.lang.Object 之外,所有的 java 类都有父类,因此除了 java.lang.Object 外,所有 Java 类的父类索引都不为 0。

接口索引集合用来描述这个类实现了那些接口,这些被实现的接口将按 implements (如果这个类本身是接口的话则是extends) 后的接口顺序从左到右排列在接口索引集合中。

2.6 字段表集合

    u2             fields_count;
    field_info     fields[fields_count];

字段表(field info)用于描述接口或类中声明的变量。字段包括类级变量以及实例变量,但不包括在方法内部声明的局部变量。

field info(字段表) 的结构:

  • access_flags: 字段的作用域(public ,private,protected修饰符),是实例变量还是类变量(static修饰符),可否被序列化(transient 修饰符),可变性(final),可见性(volatile 修饰符,是否强制从主内存读写)。
  • name_index: 对常量池的引用,表示的字段的名称;
  • descriptor_index: 对常量池的引用,表示字段和方法的描述符;
  • attributes_count: 一个字段还会拥有一些额外的属性,attributes_count 存放属性的个数;
  • attributes[attributes_count]: 存放具体属性具体内容。

上述这些信息中,各个修饰符都是布尔值,要么有某个修饰符,要么没有,很适合使用标志位来表示。而字段叫什么名字、字段被定义为什么数据类型这些都是无法固定的,只能引用常量池中常量来描述。

字段的 access_flag 的取值:

2.7 方法表集合

    u2             methods_count;
    method_info    methods[methods_count];

methods_count 表示方法的数量,而 method_info 表示方法表。

Class 文件存储格式中对方法的描述与对字段的描述几乎采用了完全一致的方式。方法表的结构如同字段表一样,依次包括了访问标志、名称索引、描述符索引、属性表集合几项。

method_info(方法表的) 结构:

方法表的 access_flag 取值:

注意:因为volatile修饰符和transient修饰符不可以修饰方法,所以方法表的访问标志中没有这两个对应的标志,但是增加了synchronizednativeabstract等关键字修饰方法,所以也就多了这些关键字对应的标志。

2.8 属性表集合

   u2             attributes_count;
   attribute_info attributes[attributes_count];

在 Class 文件,字段表,方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。与 Class 文件中其它的数据项目要求的顺序、长度和内容不同,属性表集合的限制稍微宽松一些,不再要求各个属性表具有严格的顺序,并且只要不与已有的属性名重复,任何人实现的编译器都可以向属性表中写 入自己定义的属性信息,Java 虚拟机运行时会忽略掉它不认识的属性。

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

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

相关文章

学渣的愤怒!自考本科能不能不考英语和数学?

英语和高数哪个更难? 这是自考生们最头大的两个科目。 自考高数有多难? 高数主要有微积分、线性代数和概率论三个部分。 其中微积分是基础、也是重要的一部分,不仅涉及到很多抽象概念和符号运算,还需要具备良好的计算能力和逻…

简单的洗牌算法

目录 前言 问题 代码展现及分析 poker类 game类 Text类 前言 洗牌算法为ArrayList具体使用的典例,可以很好的让我们快速熟系ArrayList的用法。如果你对ArrayList还不太了解除,推荐先看本博主的ArrayList的详解。 ArrayList的详解_WHabcwu的博客-CSD…

C++笔记之单例模式

C笔记之单例模式 参考笔记&#xff1a;C笔记之call_once和once_flag code review 文章目录 C笔记之单例模式1.返回实例引用2.返回实例指针3.单例和智能指针share_ptr结合4.单例和std::call_once结合5.单例和std::call_once、unique_ptr结合 1.返回实例引用 代码 #include <…

数据结构之队列详解(包含例题)

一、队列的概念 队列是一种特殊的线性表&#xff0c;特殊之处在于它只允许在表的前端&#xff08;front&#xff09;进行删除操作&#xff0c;而在表的后端&#xff08;rear&#xff09;进行插入操作&#xff0c;和栈一样&#xff0c;队列是一种操作受限制的线性表。进行插入操…

亿发创新中医药信息化解决方案,自动化煎煮+调剂,打造智能中药房

传统中医药行业逐步复兴&#xff0c;同时互联网科技和人工智能等信息科技助力中医药行业逐步实现数字化转型。利用互联网、物联网、大数据等科技&#xff0c;实现现代科学与传统中医药的结合&#xff0c;提供智能配方颗粒调配系统、中药自动化调剂系统、中药煎配智能管理系统、…

【Docker报错】docker拉取镜像时报错:no such host

报错信息 [rootSoft soft]# docker pull mysql Using default tag: latest Error response from daemon: Head "https://registry-1.docker.io/v2/library/mysql/manifests/latest": dial tcp: lookup registry-1.docker.io on 192.168.80.2:53: no such host解决方法…

Leetcode-每日一题【剑指 Offer 28. 对称的二叉树】

题目 请实现一个函数&#xff0c;用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样&#xff0c;那么它是对称的。 例如&#xff0c;二叉树 [1,2,2,3,4,4,3] 是对称的。 1 / \ 2 2 / \ / \ 3 4 4 3 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称…

Android 网络编程-网络请求

Android 网络编程-网络请求 文章目录 Android 网络编程-网络请求一、主要内容二、开发网络请求前的基本准备1、查看需要请求的网址是否有效&#xff08;1&#xff09;通过网页在线验证&#xff08;2&#xff09;使用专用window网咯请求工具&#xff08;3&#xff09;编写app代码…

多维时序 | MATLAB实现WOA-CNN-BiGRU-Attention多变量时间序列预测

多维时序 | MATLAB实现WOA-CNN-BiGRU-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现WOA-CNN-BiGRU-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | MATLAB实现WOA-CNN-BiGRU-Attention多变量时间序列预测 1.程…

LVS负载均衡集群-NAT模式部署

集群 集群&#xff1a;将多台主机作为一个整体&#xff0c;然后对外提供相同的服务 集群使用场景&#xff1a;高并发的场景 集群的分类 1.负载均衡器集群 减少响应延迟&#xff0c;提高并发处理的能力 2&#xff0c;高可用集群 增强系统的稳定性可靠性&…

LeetCode 141.环形链表

文章目录 &#x1f4a1;题目分析&#x1f4a1;解题思路&#x1f514;接口源码&#x1f4a1;深度思考❓思考1❓思考2 题目链接&#x1f449; LeetCode 141.环形链表&#x1f448; &#x1f4a1;题目分析 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中…

Echarts地图-全国主要城市空气质量【亲测有效】

参考&#xff1a; Echarts官网实例 效果&#xff1a; 需要通过ajax的方式获取json数据: {"code":100,"msg":"处理成功&#xff01;","extend":{"items":[{"name":"三亚","value":52},{&qu…

适合程序员的DB性能测试工具 JMeter

背景 1、想要一款既要能压数到mysql&#xff0c;又要能压数到postGre&#xff0c;还要能压数到oracle的自动化工具 2、能够很容易编写insert sql&#xff08;因为需要指定表和指定字段类型压数据&#xff09;&#xff0c;然后点击运行按钮后&#xff0c;就能直接运行&#xff…

精彩回顾 | 迪捷软件出席2023ATC汽车电子与软件技术周

2023年8月18日&#xff0c;由ATC汽车技术会议主办&#xff0c;上海市集成电路行业协会支持的“2023ATC汽车电子与软件技术周”在上海市圆满落幕。迪捷软件上海参展之行圆满收官。 ▲开幕式 本次峰会汇聚了整车厂、汽车零部件集团、软硬件方案提供商、软件工具供应商、软件测试…

利用console提高写bug的效率

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 自从入坑前端后&#xff0c;日常写bug就没离开过console。 要说用得多&#xff0c;不如说是console.log用得多&#xff0c;console.warn和console.erro…

shell脚本基础

目录 前言 一、概述 &#xff08;一&#xff09;、shell脚本基础概念 &#xff08;二&#xff09;、shell的类型 二、Shell变量 &#xff08;一&#xff09;、组成 1.变量名 2.变量值 &#xff08;二&#xff09;、类型 1.系统内置变量&#xff08;环境变量&#xff09; 2.自定…

Spring-3-Spring AOP概念全面解析

今日目标 能够理解AOP的作用 能够完成AOP的入门案例 能够理解AOP的工作流程 能够说出AOP的五种通知类型 一、AOP 1 AOP简介 思考&#xff1a;什么是AOP,AOP的作用是什么&#xff1f; 1.1 AOP简介和作用【理解】 AOP(Aspect Oriented Programming)面向切面编程&#xff0c;一…

c51单片机串口通信(中断方式接收数据)(单片机--单片机通信)示例代码 附proteus图

单片机一般采用中断方式接受数据&#xff0c;这样便于及时处理 #include "reg51.h" #include "myheader.h" #define uchar unsigned char int szc[10]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; int bufferc[6]{0}; int sza[6]{0x01,0x02,0x0…

接口测试及接口抓包常用测试工具和方法?

作为测试领域中不可或缺的一环&#xff0c;接口测试和抓包技术在软件开发过程中扮演着至关重要的角色。不论你是新手还是有一些经验的小伙伴&#xff0c;本篇文章都会为你详细介绍接口测试的基本概念、常用测试工具和实际操作技巧&#xff0c;让你轻松掌握这一技能。 接口测试…

MySQL之索引和事务

什么是索引索引怎么用索引的原理事务使用事务事务特性MySQL隔离级别 什么是索引 索引包含数据表所有记录的引用指针&#xff1b;你可以对某一列或者多列创建索引和指定不同的类型&#xff08;唯一索引、主键索引、普通索引等不同类型&#xff1b;他们底层实现也是不同的&#…