范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

class字节码文件格式详解

  class字节码文件格式
  掌握jvm 字节码,最关键的是学习class文件格式以及字节码指令集等细节,今天我们来学习class字节码文件格式(jdk8版本)。
  Java代码经过javac编译器编译成class文件,JVM虚拟机读取class文件执行其中的代码。
  通过JVM虚拟机规范,实现了jvm跨平台、跨语言的能力,JVM规范中非常重要的一部分就是class字节码文件格式。 class文件结构
  class文件的整体结构如下图所示,其中u1,u2,u4分别表示1个、2个、4个字节长度的无符号数据,无符号byte数据按照具体的场景可以用来表示数字、字符等。 结构中还可以使用复合结构,比如cp_info, cp_info结构也会在规范中进行定义。 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]; } magic
  魔法字符串,固定为0xCAFEBABE minor_version, major_version
  分别是class文件的小版本号和大版本号,jvm规范要求运行的jvm版本必须大于等于(更严格说是能支持,不过目前大于等于即可)class文件的major_version才能运行,否则抛出异常。 constant_pool_count
  常量池数量,是下面的常量池表的长度加一,因为index=0的常量引用没有使用。 constant_pool[]
  常量池表,每个常量池的结构cp_info如下,常量池可以表示字符串常量、类名、接口名、方法等信息,这些常量池会在class文件中其他地方进行引用(比如字段中字段类型、字段名等)。 常量通过index进行引用,常量之间也可以通过index进行引用。
  cp_info中的tag字段用来标识当前的常量类型,不同的常量类型有不同的子结构,然后就可以用具体的结构来解析info[]这个byte数组。 常量的结构有, cp_info {     u1 tag;     u1 info[]; }
  Constant type
  tag value
  CONSTANT_Class
  7
  CONSTANT_Fieldref   9
  CONSTANT_Methodref   10
  CONSTANT_InterfaceMethodref   11
  CONSTANT_Integer   3
  CONSTANT_Float   4
  CONSTANT_Long   5
  CONSTANT_Double   6
  CONSTANT_NameAndType   12
  CONSTANT_Utf8   1
  CONSTANT_MethodHandle   15
  CONSTANT_MethodType   16
  CONSTANT_InvokeDynamic   18
  我们提前查看一下各个常量类型的结构,给后面介绍Field, Method做铺垫。 CONSTANT_Class_info { u1 tag; u2 name_index; } CONSTANT_Class_info   CONSTANT_Class_info表示类或接口 CONSTANT_Class_info { u1 tag; u2 name_index; }   tag: 是CONSTANT_Class对应的值(7) name_index: name_index是这个类或接口的类名的字符串常量的index CONSTANT_Fieldref_info, CONSTANT_Methodref_info, CONSTANT_InterfaceMethodref_infoCONSTANT_Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; }   字段引用、方法引用、接口方法引用这三个结构比较类似,都是各自的tag以及class_index和name_and_type_index   class_index: 这个字段、方法所在类的class的常量的index   name_and_type_index: 这个字段的名称和类型结构常量CONSTANT_NameAndType_info的index。name分别是字段名和方法名,类型是字段、方法的descriptor描述符。 CONSTANT_String_info   字符串常量结构   string_index: 指向CONSTANT_Utf8_info的index CONSTANT_String_info { u1 tag; u2 string_index; } CONSTANT_Integer_info, CONSTANT_Float_info   整数和浮点数常量结构,对应的数值占用4个字节。 CONSTANT_Integer_info { u1 tag; u4 bytes; } CONSTANT_Float_info { u1 tag; u4 bytes; } CONSTANT_Long_info, CONSTANT_Double_info   这两个常量结构分别存储long和double类型的数值,大小占用8个字节 high_bytes和low_bytes分别表示高位和低位的数据,以long为例,对应值为((long) high_bytes << 32) + low_bytes CONSTANT_Long_info { u1 tag; u4 high_bytes; u4 low_bytes; } CONSTANT_Double_info { u1 tag; u4 high_bytes; u4 low_bytes; } CONSTANT_NameAndType_info   CONSTANT_NameAndType_info常量用来表示名称和类型,在前面的CONSTANT_Fieldref_info, CONSTANT_Methodref_info, CONSTANT_InterfaceMethodref_info 常量中有使用,结构如下 CONSTANT_NameAndType_info { u1 tag; u2 name_index; u2 descriptor_index; }   name_index: 指向对应名称的utf8常量的CONSTANT_Utf8_info的index descriptor_index: 指向类型描述符的CONSTANT_Utf8_info的index。 Field Descriptor和Method Descriptor   在jvm中,数据分为primitive type(基本类型,比如int, long)和reference type(引用类型),类型的描述符规则如下   类型   描述符   byte   B   char   C   double   D   float   F   int   I   long   J   short   S   boolean   Z   reference,引用类型   LClassName;   数组   [   引用类型的ClassName是/间隔的字符串,比如java.lang.String的描述符为Ljava/lang/String; 数组是在对应的类型前加[,比如int[]描述符为[I, String[]描述符为[Ljava/lang/String;, 多维数组距离 int[][]描述符为[[I   Field Descriptor是对应字段的类型的描述符 Method Descriptor为( {ParameterDescriptor} ) ReturnDescriptor,比如public String test(int a, Long b)的方法描述符为(ILjava/lang/Long)Ljava/lang/String;,如果返回值是void,则使用V CONSTANT_Utf8_info   CONSTANT_Utf8_info常量存储utf8编码的字符串内容,包含一个字符串长度字段和对应长度的byte数组。 CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; } class access_flags   access_flags用来表示当前类的一些bit信息(类似bitmap),这样用2个字节的空间就可以表示16个标记信息。   Flag Name   Value   表头   ACC_PUBLIC   0x0001   表示当前类/接口是否是public   ACC_FINAL   0x0010   是否声明了final   ACC_SUPER   0x0020   都是true, 为了兼容旧版本的字节码的标记   ACC_INTERFACE   0x0200   是否是接口   ACC_ABSTRACT   0x0400   是否是抽象类,接口也是抽象类   ACC_SYNTHETIC   0x1000   表示不是代码中生成的类,比如jdk为实现lambda表达式在运行时生成的一些类   ACC_ANNOTATION   0x2000   是否是@interface这样的注解类   ACC_ENUM   0x4000   是否枚举类 Fields   Fields是field_info的数组,每个field_info结构如下。 field_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; }   access_flags: 字段的access_flags,和class的access_flags类似,用来描述字段的public,private,volatile等等标识信息。   Flag Name   Value   描述   ACC_PUBLIC   0x0001   是否是public字段   ACC_PRIVATE   0x0002   是否是private字段   ACC_PROTECTED   0x0004   是否是static字段   ACC_STATIC   0x0008   是否是static字段   ACC_FINAL   0x0010   是否是final字段   ACC_VOLATILE   0x0040   是否是volatile字段   ACC_TRANSIENT   0x0080   是否是transient字段   ACC_SYNTHETIC   0x1000   单元格   ACC_ENUM   0x4000   单元格   name_index: 字段名称的CONSTANT_Utf8_info常量index descriptor_index: 字段类型描述符的CONSTANT_Utf8_info常量index attributes_count: 字段的属性数量 attributes: 字段的属性,结构为attribute_info,比如ConstantValue,描述常量字段的常量值,属性的结构稍后介绍。 Methods   类中所有的方法包括构造函数()、静态初始化方法(),都使用method_info结构,在一个类中,方法名称和方法签名联合起来必须唯一 method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; }   access_flags: 方法的标识数据,包括public, private, synchronized等等信息   Flag Name   Value   描述   ACC_PUBLIC   0x0001   public方法   ACC_PRIVATE   0x0002   private方法   ACC_PROTECTED   0x0004   protected方法   ACC_STATIC   0x0008   static方法   ACC_FINAL   0x0010   final方法   ACC_SYNCHRONIZED   0x0020   synchronized方法(方法维度的synchronized声明,不同于synchronized代码块的monitor_enter和monitor_exit)   ACC_BRIDGE   0x0040   是否是transient字段   ACC_VARARGS   0x0080   有可变参数的方法   ACC_NATIVE   0x0100   native方法   ACC_ABSTRACT   0x0400   抽象方法   ACC_STRICT   0x0800   浮点数模式是FT-strict的,这个很少见   ACC_SYNTHETIC   0x1000   是否是合成方法,即不再源代码中的方法   name_index: 指向方法名的CONSTANT_Utf8_info常量 descriptor_index: 指向方法描述符的CONSTANT_Utf8_info常量 attributes_count: 方法的属性数量 attributes[]: 方法的各个属性,其中比较关键的是名字为Code的属性,包含的是方法体的字节码指令。 Attributes属性   Attributes属性在classfile, field_info, method_info中都有使用,结构如下 attribute_info { u2 attribute_name_index; u4 attribute_length; u1 info[attribute_length]; }   attribute_name_index: 指向属性的名称的CONSTANT_Utf8_info常量 attribute_length: 属性信息的字节长度,即info的长度 info[]: 属性的具体信息,每种属性有自己的结构   属性有ConstantValue,Code,StackMapTable,Exceptions,BootstrapMethods等等很多种属性,我们这里重点介绍一下ConstantValue和Code。 ConstantValue属性   常量值属性用来表示常量字段的常量值,数值(int,long,float等)和字符串字段能够声明成常量。 ConstantValue_attribute { u2 attribute_name_index; u4 attribute_length; u2 constantvalue_index; }   attribute_name_index: 指向"ConstantValue"的CONSTANT_Utf8_info attribute_length: 2,因为constantvalue_index是两个byte长度的index constantvalue_index: 指向具体的常量池中的常量,按照类型不同分为CONSTANT_Long,CONSTANT_Float,CONSTANT_Double,CONSTANT_Integer(int, short, char, byte, boolean都用CONSTANT_Integer),CONSTANT_String, Code属性   Code属性用来表示方法体中的代码字节码。 Code_attribute { u2 attribute_name_index; u4 attribute_length; u2 max_stack; u2 max_locals; u4 code_length; u1 code[code_length]; u2 exception_table_length; { u2 start_pc; u2 end_pc; u2 handler_pc; u2 catch_type; } exception_table[exception_table_length]; u2 attributes_count; attribute_info attributes[attributes_count]; }   attribute_name_index: 指向"Code"的CONSTANT_Utf8_info常量 attribute_length: 后面所有的字段信息的字节数 max_stack: 方法的字节码指令执行过程中需要的操作数栈的最大栈层数,关于方法字节码指令的执行,在字节码指令文章中进行介绍。 max_locals: 方法的字节码指令执行过程中需要的本地变量表的最大长度(注意局部变量表的元素长度是4字节,long和double变量在局部变量表中占两个位置) code_length: 方法体的字节码的长度 code[]: 方法体的字节码 exception_table_length: 异常表的长度 exception_table[]: 异常表数组,每个异常表包含start_pc,end_pc,handler_pc,catch_type。pc是指code[]数组中的索引,也就是从code[]字节码数组start_pc(包含)到end_pc(不包含)中的字节码执行时出现catch_type(指向异常类的CONSTANT_Class_info常量)异常,则转到code[]的handler_pc位置来处理异常。 attributes_count: Code属性的数量 attributes[]: Code属性数组,比如LineNumberTable,LocalVariableTable, LocalVariableTypeTable, StackMapTable   其他的属性可以参考jvm规范 如何解析class文件   假如我们现在有一个class文件,想去查看其中的Java源代码,该如何实现呢?有如下几种方法。 通过javap   javap是jdk里自带的反编译工具,可以打印出更加可读的class字节码信息。 javap -c -cp /Users/liuzhengyang/Code/work/code-test/target/classes/ test.Test Compiled from "Test.java" public class test.Test { public test.Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return public java.lang.String hello(); Code: 0: ldc #2 // String hello world 2: areturn }   javap参数说明   参数   说明   -cp   指定classpath, javap需要到classpath中寻找class文件   -p   默认情况下javap不打印出private的方法、字段,通过-p可以打印全部信息   -c   默认情况下javap不打印出方法的body字节码,通过-c可以打印   -v   打印最全的信息,包括常量池、方法stack size、方法本地变量表等等 通过IDEA反编译   把class文件拖动到IDEA中即可查看到反编译的java代码结果,相比javap更加易读。 通过arthas jad命令   如果要查看运行中的程序中使用到的代码,可以使用arthas的[jad](https://arthas.aliyun.com/doc/jad.html)命令。 更多资料   更详细的资料包括java语言规范、java虚拟机规范可以在[Java Language and Virtual Machine Specifications](https://docs.oracle.com/javase/specs/index.html)中找到 总结   本篇文章介绍了class文件的结构,包括常量池、字段、方法、属性等,详细了解了每个数据的结构,最后了解查看class文件的几种方式。

从三分天下到群雄割据,直播如何搅动电商江湖?创业公司负责试错,中型公司负责验证,巨头负责清场,这是过去互联网商业竞争的一条铁律。但现在被直播电商打破了,变成了巨头试错,小巨头验证清场了。早在2015年就躬身直播电商的淘宝,在安奈儿大额定增正式获批会否引起市场关注2021年2月2日通过分析各大头部券商纺织品鞋服行业研究报告,其中国信证券的研报表明,儿童鞋服为是鞋服行业中增长最快的赛道之一。中国现在已经成为世界第一大服装市场,多年来保持较高的博鳌亚洲论坛携手杜国楹小罐茶告诉你,喝茶有讲究作为五千年历史的文明古国,中国孕育出了独特的中华文化。而茶是中国文化代表之一,全世界一百多个国家和地区的人喜爱品茶。而中国茶文化反映出中华民族的悠久的文明和礼仪。杜国楹遍访专家,打2021璞梵首次亮相,一如梵响人间最美四月天,2021年成都迎来了第104届中国食品行业的盛会。毋庸置疑,今年的春糖有着不同以往的意义。因为疫情导致2020年春糖的暂停,今年的春季糖酒会于疫情之后重磅登场,承载房车就是简单改装?老司机表示,你想的太简单了2021年的春节与往年有所不同,虽然不至于像去年那样全面封城而导致万人空巷,但由于疫情并未完全消除,不少人在假期期间外出游玩还是多了几分顾虑,乘坐公共交通工具出行的人数大幅减少,而快速回本,快速挣钱上汽大通MAXUSEV30让宋浩赞不绝口最近国内疫情又有所反复,高风险地区有不少人的生计将再次受到影响。不过对于深圳蛇口的宋浩来说,这并不是什么大问题。上一次春节那波疫情导致他失业,他在朋友建议下购买了一款上汽大通MAX年报季迫近看中芯国际光峰科技等如何撰写社会责任报告来源小多金服ESG概念想要写好一份企业社会责任ESG报告,那就先要知道什么ESG。其实,对于境内上市公司,ESG就是更加高大上版的企业社会责任(CSR)。ESG全称为Environ美国网件公司(NETGEAR)推出全新夜鹰RAXE500三频WiFi6E路由器中国4月21日美国网件公司(NETGEAR)(NASDAQ代码NTGR),作为全球领先的家用和商用先进联网产品供应商,在CES2021期间,NETGEAR推出了世界上首款WiFi6ATENVS182A2端口4KHDMI影音分配器ATENVS182A是什么?VS182AHDMI影音分配器对于需要将高清视频分辨率数字信号复制输出到2台显示设备的用户而言,是一套非常理想的解决方案。VS182A可支持具备HDMI通信服务头部民营企业润建股份002929预中标大合同公告解读2021年2月19日近日,我国年客运量最大的航空公司中国南方航空,发布了一项未来三年总计超14亿元的服务外包采购项目中标候选人信息。据了解,此次招标项目为南航20212023年度服升级版KeyMander2Mobile键盘鼠标转换器震撼上市随着手游市场的突飞猛进,全民电竞时代正悄然开启。尤其随着AppleArcade和GoogleStadia等游戏平台开始与PlayStationXbox等传统游戏主机展开竞争后,手游
拼多多砍价到小数点后6位还是失败是真还是假拼多多砍价到小数点后6位依旧失败看见拼夕夕就觉得恶心,里面好多通知都是强行的,比如每次买东西,物流每更新一次,它就提醒一次,并且不可以关,真是恶心它妈妈遇到他爸爸,然后恶心到家。还Web3。0,并不仅仅只是一个入口文孟永辉简单地按照横向的逻辑来看待Web3。0,并不能够真正理解Web3。0的内涵,甚至还将会把Web3。0带入到类似Web1。0和Web2。0的发展境地里。然而,这种倾向却是现在断供打开潘多拉魔盒!反制措施出炉,科技秩序或将迎来重建潘多拉魔盒自今年2月以来,包括微软谷歌英特尔英伟达AMD甲骨文三星高通苹果在内的企业纷纷选择停止在俄业务,断供这一威力和破坏巨大的手段再次被使用。无论是芯片数据库还是智能手机,对于小米平板5pro上手照通过最终的筛选和纠结,还是选择了同品牌的小米平板,小米5pro整体上手来说,感觉不算太重的同时又感觉重。两个手拿着边框很割手(金属边框,塑料背板)我买的是6128G内存基本款(看好新能源汽车公共充电桩是快充还是慢充新能源汽车公共充电桩是快充,快充和慢充最大的区别在于快充是直流充电桩充电接口,把电网的交流电转化成直流电,输送到电动汽车的快充口,电能直接进入电池充电。慢充是交流充电桩充电接口,把理想L9阿维塔11护卫舰07北京车展值得关注的新能源车前瞻虽然最近这波疫情肆虐,让今年4月份的北京车展能不能如期举办充满了变数,但并不妨碍我们对这个上半年最重要的汽车展会充满期待。毕竟,从目前已知的消息来看,这次北京车展将有非常多的重磅车如果手机出现4种情况,建议直接换新,3个细节教你挑选耐用机型随着国产手机技术的不断提高,国人的换机周期也在变长。很多用户也遇到一个纠结的情况,手机用着用着总觉得不顺手,想要换掉,又觉得还能用不要浪费不换掉吧,自己用着又感觉不太舒服。今天想告入职字节跳动的第一天这城市只有我一个人?10年前,字节跳动的Day1从知春路上的一间民居开始10年后,每天都有亿万用户通过字节跳动的各个产品激发创造,分享美好。如今,Day1已经不再是某个具体的日子,而是一种不守成不自满特斯拉车顶维权女主AB面僵持争议与一连串官司作者李想来源产业科技时隔数月,特斯拉与上海车展维权女主张女士的纠纷仍在僵持中。近日,张女士在接受媒体采访时透露,她与特斯拉的数起案件有新进展,其中起诉特斯拉侵犯个人车辆数据纠纷一案比亚迪e9,外观帅气,空间宽裕,内饰设计柔美,配纯电动222马力近几年随着汽车普及,中大型车已经成为办公人事商务出行的常备车。不少消费者最先想到的是驾驶体验较为舒适,其实除了较好的驾驶体验外,一些品牌车在颜值方面也下足了功夫。今天给大家介绍的是CentOS7宝塔面板MinIO安装部署服务开机启动安装minio服务下载minio,建议下载到usrlocalbin目录下,可全局访问wgethttpsdl。minio。ioserverminioreleaselinuxamd64