百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

JVM系列-5.认识class文件

lipiwang 2024-11-20 18:31 8 浏览 0 评论

class文件,也就是编译后生成的字节码文件。我们可以使用一些文本工具将它打开,比如UE或者Sublime Text,打开后可以看到如下内容(16进制):

当然,这样的内容是没法直接通过阅读来了解其含义的,此处只需要对其有个直观了解即可,下面将会通过javap指令来进行class文件反解析,得到易于阅读的文本展示。

Class文件结构

据上图中的叙述,我们可以将class的文件组织结构概括成以下面这个表格(其中u表示u4表示4个无符号字节,u2表示2个无符号字节):

下面我们结合表格和示意图对每个部分进行介绍:

魔数

所有的由Java编译器编译而成的class文件的前4个字节都是“0xCAFEBABE”。

它的作用在于:当JVM在尝试加载某个文件到内存中来的时候,会首先判断此class文件有没有JVM认为可以接受的“签名”,即JVM会首先读取文件的前4个字节,判断该4个字节是否是“0xCAFEBABE”,如果是,则JVM会认为可以将此文件当作class文件来加载并使用。

版本号

随着Java本身的发展,Java语言特性和JVM虚拟机也会有相应的更新和增强。目前我们能够用到的JDK版本如:1.5,1.6,1.7,还有现如今的1.8及更高的版本。发布新版本的目的在于:在原有的版本上增加新特性和相应的JVM虚拟机的优化。而随着主版本发布的次版本,则是修改相应主版本上出现的bug。我们平时只需要关注主版本就可以了。

主版本号和次版本号在class文件中各占两个字节,副版本号占用第5、6两个字节,而主版本号则占用第7,8两个字节。JDK1.0的主版本号为45,以后的每个新主版本都会在原先版本的基础上加1。若现在使用的是JDK1.7编译出来的class文件,则相应的主版本号应该是51,对应的7,8个字节的十六进制的值应该是 0x33。

一个JVM实例只能支持特定范围内的主版本号 (Mi 至Mj) 和 0 至特定范围内 (0 至 m) 的副版本号。假设一个 Class 文件的格式版本号为 V, 仅当Mi.0 ≤ v ≤ Mj.m成立时,这个 Class 文件才可以被此 Java 虚拟机支持。不同版本的 Java 虚拟机实现支持的版本号也不同,高版本号的 Java 虚拟机实现可以支持低版本号的 Class 文件,反之则不成立。

JVM在加载class文件的时候,会读取出主版本号,然后比较这个class文件的主版本号和JVM本身的版本号,如果JVM本身的版本号 < class文件的版本号,JVM会认为加载不了这个class文件,会抛出我们经常见到的" java.lang.UnsupportedClassVersionError: Bad version number in .class file "Error 错误;反之,JVM会认为可以加载此class文件,继续加载此class文件。

程序抛出:"java.lang.UnsupportedClassVersionError:Bad version number in .class fifile"时的解决方法:

a). 重新使用当前jvm编译源代码,然后再运行代码;

b). 将当前JVM虚拟机更新到class文件的版本。

查看class文件的版本号方法:可以借助于文本编辑工具,直接查看该文件的7,8个字节的值,确定class文件是什么版本的。更快捷的方式使用JDK自带的javap工具,使用javap -v class文件

常量池计数器

常量池是class文件中非常重要的结构,它描述着整个class文件的字面量信息。常量池是由一组constant_pool结构体数组组成的,而数组的大小则由常量池计数器指定。常量池计数器constant_pool_count 的值 =constant_pool表中的成员数+ 1。constant_pool表的索引值只有在大于 0且小于constant_pool_count时才会被认为是有效的。

注意事项:常量池计数器默认从1开始而不是从0开始:当constant_pool_count = 1时,常量池中的cp_info个数为0;当constant_pool_count为n时,常量池中的cp_info个数为n-1。

原因:在指定class文件规范的时候,将索引#0项常量空出来是有特殊考虑的,当某些数据在特定的情况下想表达“不引用任何一个常量池项”的意思时,就可以将其引用的常量的索引值设置为#0来表示。

常量池数据区

访问标志

访问标志,access_flags 是一种掩码标志,用于表示某个类或者接口的访问权限及基础属性。

类索引

类索引,this_class的值必须是对constant_pool表中项目的一个有效索引值。constant_pool表在这个索引处的项必须为CONSTANT_Class_info 类型常量,表示这个 Class 文件所定义的类或接口。

父类索引

  1. 父类索引,对于类来说,super_class 的值必须为 0 或者是对constant_pool 表中项目的一个有效索引值。
  2. 如果它的值不为 0,那 constant_pool 表在这个索引处的项必须为CONSTANT_Class_info 类型常量,表示这个 Class 文件所定义的类的直接父类。当前类的直接父类,以及它所有间接父类的access_flag 中都不能带有ACC_FINAL 标记。
  3. 对于接口来说,它的Class文件的super_class项的值必须是对constant_pool表中项目的一个有效索引值。
  4. constant_pool表在这个索引处的项必须为代表 java.lang.Object 的 CONSTANT_Class_info 类型常量 。
  5. 如果 Class 文件的 super_class的值为 0,那这个Class文件只可能是定义的是java.lang.Object类,只有它是唯一没有父类的类。

接口计数器

接口计数器,interfaces_count的值表示当前类或接口的【直接父接口数量】

接口信息数据区

接口表,interfaces[]数组中的每个成员的值必须是一个对constant_pool表中项目的一个有效索引值, 它的长度为 interfaces_count。每个成员interfaces[i] 必须为CONSTANT_Class_info类型常量,其中 【0 ≤ i <interfaces_count】。在interfaces[]数组中,成员所表示的接口顺序和对应的源代码中给定的接口顺序(从左至右)一样,即interfaces[0]对应的是源代码中最左边的接口。

字段计数器

字段计数器,fields_count的值表示当前 Class 文件 fields[]数组的成员个数。 fields[]数组中每一项都是一个field_info结构的数据项,它用于表示该类或接口声明的【类字段】或者【实例字段】。

字段信息数据区

字段表,fields[]数组中的每个成员都必须是一个fields_info结构的数据项,用于表示当前类或接口中某个字段的完整描述。 fields[]数组描述当前类或接口声明的所有字段,但不包括从父类或父接口继承的部分。

方法计数器

方法计数器, methods_count的值表示当前Class 文件 methods[]数组的成员个数。Methods[]数组中每一项都是一个 method_info 结构的数据项。

方法信息数据区

方法表,methods[] 数组中的每个成员都必须是一个 method_info 结构的数据项,用于表示当前类或接口中某个方法的完整描述。

如果某个method_info 结构的access_flags 项既没有设置 ACC_NATIVE 标志也没有设置ACC_ABSTRACT 标志,那么它所对应的方法体就应当可以被 Java 虚拟机直接从当前类加载,而不需要引用其它类。

method_info结构可以表示类和接口中定义的所有方法,包括【实例方法】、【类方法】、【实例初始化方法】和【类或接口初始化方法】。

methods[]数组只描述【当前类或接口中声明的方法】,【不包括从父类或父接口继承的方法】。

属性计数器

属性计数器,attributes_count的值表示当前 Class 文件attributes表的成员个数。attributes表中每一项都是一个attribute_info 结构的数据项。

属性信息数据区

属性表,attributes 表的每个项的值必须是attribute_info结构。

在Java 7 规范里,Class文件结构中的attributes表的项包括下列定义的属性: InnerClasses、 EnclosingMethod 、 Synthetic 、Signature、SourceFile,SourceDebugExtension、Deprecated、RuntimeVisibleAnnotations 、RuntimeInvisibleAnnotations以及BootstrapMethods属性。

对于支持 Class 文件格式版本号为 49.0 或更高的 Java 虚拟机实现,必须正确识别并读取attributes表中的Signature、RuntimeVisibleAnnotations和RuntimeInvisibleAnnotations属性。对于支持Class文件格式版本号为 51.0 或更高的 Java虚拟机实现,必须正确识别并读取 attributes表中的BootstrapMethods属性。Java 7 规范 要求任一 Java 虚拟机实现可以自动忽略 Class 文件的 attributes表中的若干 (甚至全部) 它不可识别的属性项。任何本规范未定义的属性不能影响Class文件的语义,只能提供附加的描述信息 。

以上就是class字节码文件的整体结构

相关推荐

《每日电讯报》研发数字工具,教你更有效率地报道新闻

为鼓励新闻编辑部持续创新,《每日电讯报》正在尝试有战略地研发数字工具。网站的数字媒体主任马尔科姆o科尔斯(MalcolmColes)表示,《每日电讯报》正试图去“创建一些可持续资产”,以便于让记者们...

html5学得好不好,看掌握多少标签

html5你了解了多少?如果你还是入门阶段的话,或者还是一知半解的话,那么我们专门为你们收集的html5常用的标签大全对你就很有帮助了,你需要了解了html5有哪些标签你才能够更好的。驾驭html5...

前端分享-少年了解过iframe么(我想了解少年)

iframe就像是HTML的「内嵌画布」,允许在页面中加载独立网页,如同在画布上叠加另一幅动态画卷。核心特性包括:独立上下文:每个iframe都拥有独立的DOM/CSS/JS环境(类似浏...

做SEO要知道什么是AJAX(人能看到但搜索引擎看不到的内容)

一个明显的,人能看到但搜索引擎不能看到的内容是AJAX。那么什么是AJAX呢?其实,了解过的基本上也都清楚,AJAX不是新的编程语言,而是一种使用现有标准的新方法。AJAX最大的优点是在不重新加...

介绍最前沿的人工智能创新,‘无反向传播’神经网络训练方法?

图像由GoogleImageFX生成前言:本文整理自NoProp原始论文与实践代码,并结合多个公开实现细节进行了全流程复现。对神经网络训练机制的探索仍在不断演进,如果你也在研究反向传播之...

说说我们对HTML6的期许(对html的看法)

HTML5概述HTML5是HTML语言最受欢迎的版本之一,它支持音频和视频、离线存储、移动端、和标签属性等等。还提供了article,section,header这样的标签来帮助开发者更好...

浏览器中在线预览pdf文件,pdf.mjs插件实现web预览pdf

背景:本来只是淘宝上卖卖袜子,想着扩展一下业务,准备做同名“来家居”海外袜子馆外贸项目,碰到pdf在线预览的需求,就找了pdf.js插件进行实践后把此方法记录下来,可以通过多种方法来实现,每种方法都有...

SVG 在前端的7种使用方法,你还知道哪几种?

本文简介点赞+关注+收藏=学会了技术一直在演变,在网页中使用SVG的方法也层出不穷。每个时期都有对应的最优解。所以我打算把我知道的7种SVG的使用方法列举出来,有备无患~如果你还...

HTML5常用标签大全(html5em标签)

HTML前端开发最终取决于掌握标签的多少HTML大概有七八百个标签楼主这里给大家总结了下HTML常用标签标签描述<!--...-->定义注释。<!DOCTYPE>定义文档类型...

&quot;伪君子Snoop Dogg!&quot;... WHAT?| MetroDaily 24/7

TUE.01-新作品-虽说年纪大了会有点糊涂,但是最近SnoopDogg的这波操作实在是让粉丝们有点迷,甚至有人表示没想到他是这样的"伪君子"......而这一切都源于他近日在IG上Po出的一...

史努比snoopy卡通手机壁纸屏保(史努比壁纸无水印)

...

莎夏·班克斯盼望表哥Snoop Dogg为其作出场曲

NXT女子冠军莎夏·班克斯(SashaBanks)近日接受了迈阿密先驱报采访,访谈纪要如下:关于她出众的形象:“我一向喜欢与众不同。为了能让人眼前一亮,我的装束总是非常前卫、非常抢眼,这样才能让观众...

喜欢Snoop!全球第一间「史努比博物馆」海外分馆在东京!

1950年起,由美國漫畫家CharlesM.Schulz創作的作品《Snoopy》史努比,其鮮明的可愛角色與幽默的劇情內容,至今仍成為許多大朋友與小朋友心中的最愛。為了紀念作者所設立的全球首...

Vetements 推出 Snoop Dogg 肖像「天价」T-Shirt

Vetements的CEOGuramGvasalia早前才透露品牌经营策略的秘密–Vetements如何成为人人热议的话题品牌。但似乎他仍有更多需要解释的东西–这个法国奢侈品牌最新...

狗爷Snoop Dogg的《I Wanna Thank Me》巡回演唱会旧金山站

西海岸匪帮说唱歌手SnoopDogg在《IWannaThankMe》巡回演唱会旧金山站表演(图片来自ICphoto)西海岸匪帮说唱歌手SnoopDogg(图片来自ICphoto)西海...

取消回复欢迎 发表评论: