本文共 15983 字,大约阅读时间需要 53 分钟。
//接口package com.example.jacoco;public interface Animal { public void eat();}//实现类package com.example.jacoco;public class Cat implements Animal { public static String type = "cat"; public String name; @Override public void eat(){ System.out.println("-----------eat-----------"); } public String getName() { return name; }}
cafe babe 0000 0034 002d 0700 0201 0016636f 6d2f 6578 616d 706c 652f 6a61 636f636f 2f43 6174 0700 0401 0010 6a61 76612f6c 616e 672f 4f62 6a65 6374 0700 06010019 636f 6d2f 6578 616d 706c 652f 6a61636f 636f 2f41 6e69 6d61 6c01 0004 74797065 0100 124c 6a61 7661 2f6c 616e 672f5374 7269 6e67 3b01 0004 6e61 6d65 0100083c 636c 696e 6974 3e01 0003 2829 56010004 436f 6465 0800 0e01 0003 6361 74090001 0010 0c00 0700 0801 000f 4c69 6e654e75 6d62 6572 5461 626c 6501 0012 4c6f6361 6c56 6172 6961 626c 6554 6162 6c650100 063c 696e 6974 3e0a 0003 0015 0c001300 0b01 0004 7468 6973 0100 184c 636f6d2f 6578 616d 706c 652f 6a61 636f 636f2f43 6174 3b01 0003 6561 7409 001a 001c0700 1b01 0010 6a61 7661 2f6c 616e 672f5379 7374 656d 0c00 1d00 1e01 0003 6f757401 0015 4c6a 6176 612f 696f 2f50 72696e74 5374 7265 616d 3b08 0020 0100 192d2d2d 2d2d 2d2d 2d2d 2d2d 6561 742d 2d2d2d2d 2d2d 2d2d 2d2d 0a00 2200 2407 00230100 136a 6176 612f 696f 2f50 7269 6e745374 7265 616d 0c00 2500 2601 0007 7072696e 746c 6e01 0015 284c 6a61 7661 2f6c616e 672f 5374 7269 6e67 3b29 5601 00076765 744e 616d 6501 0014 2829 4c6a 6176612f 6c61 6e67 2f53 7472 696e 673b 09000100 2a0c 0009 0008 0100 0a53 6f75 72636546 696c 6501 0008 4361 742e 6a61 76610021 0001 0003 0001 0005 0002 0009 00070008 0000 0001 0009 0008 0000 0004 0008000a 000b 0001 000c 0000 0026 0001 00000000 0006 120d b300 0fb1 0000 0002 00110000 0006 0001 0000 0004 0012 0000 00020000 0001 0013 000b 0001 000c 0000 002f0001 0001 0000 0005 2ab7 0014 b100 00000200 1100 0000 0600 0100 0000 0300 12000000 0c00 0100 0000 0500 1600 1700 00000100 1800 0b00 0100 0c00 0000 3700 02000100 0000 09b2 0019 121f b600 21b1 00000002 0011 0000 000a 0002 0000 0009 0008000b 0012 0000 000c 0001 0000 0009 00160017 0000 0001 0027 0028 0001 000c 0000002f 0001 0001 0000 0005 2ab4 0029 b0000000 0200 1100 0000 0600 0100 0000 0e001200 0000 0c00 0100 0000 0500 1600 17000000 0100 2b00 0000 0200 2c
Last modified 2019-4-7; size 779 bytes MD5 checksum e33bee3260446d95b04b553983a2f3a1 Compiled from "Cat.java"public class com.example.jacoco.Cat implements com.example.jacoco.Animal minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Class #2 // com/example/jacoco/Cat #2 = Utf8 com/example/jacoco/Cat #3 = Class #4 // java/lang/Object #4 = Utf8 java/lang/Object #5 = Class #6 // com/example/jacoco/Animal #6 = Utf8 com/example/jacoco/Animal #7 = Utf8 type #8 = Utf8 Ljava/lang/String; #9 = Utf8 name #10 = Utf8#11 = Utf8 ()V #12 = Utf8 Code #13 = String #14 // cat #14 = Utf8 cat #15 = Fieldref #1.#16 // com/example/jacoco/Cat.type:Ljava/lang/String; #16 = NameAndType #7:#8 // type:Ljava/lang/String; #17 = Utf8 LineNumberTable #18 = Utf8 LocalVariableTable #19 = Utf8 #20 = Methodref #3.#21 // java/lang/Object." ":()V #21 = NameAndType #19:#11 // " ":()V #22 = Utf8 this #23 = Utf8 Lcom/example/jacoco/Cat; #24 = Utf8 eat #25 = Fieldref #26.#28 // java/lang/System.out:Ljava/io/PrintStream; #26 = Class #27 // java/lang/System #27 = Utf8 java/lang/System #28 = NameAndType #29:#30 // out:Ljava/io/PrintStream; #29 = Utf8 out #30 = Utf8 Ljava/io/PrintStream; #31 = String #32 // -----------eat----------- #32 = Utf8 -----------eat----------- #33 = Methodref #34.#36 // java/io/PrintStream.println:(Ljava/lang/String;)V #34 = Class #35 // java/io/PrintStream #35 = Utf8 java/io/PrintStream #36 = NameAndType #37:#38 // println:(Ljava/lang/String;)V #37 = Utf8 println #38 = Utf8 (Ljava/lang/String;)V #39 = Utf8 getName #40 = Utf8 ()Ljava/lang/String; #41 = Fieldref #1.#42 // com/example/jacoco/Cat.name:Ljava/lang/String; #42 = NameAndType #9:#8 // name:Ljava/lang/String; #43 = Utf8 SourceFile #44 = Utf8 Cat.java{ public static java.lang.String type; descriptor: Ljava/lang/String; flags: ACC_PUBLIC, ACC_STATIC public java.lang.String name; descriptor: Ljava/lang/String; flags: ACC_PUBLIC static {}; descriptor: ()V flags: ACC_STATIC Code: stack=1, locals=0, args_size=0 0: ldc #13 // String cat 2: putstatic #15 // Field type:Ljava/lang/String; 5: return LineNumberTable: line 4: 0 LocalVariableTable: Start Length Slot Name Signature public com.example.jacoco.Cat(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #20 // Method java/lang/Object." ":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/example/jacoco/Cat; public void eat(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: getstatic #25 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #31 // String -----------eat----------- 5: invokevirtual #33 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return LineNumberTable: line 9: 0 line 11: 8 LocalVariableTable: Start Length Slot Name Signature 0 9 0 this Lcom/example/jacoco/Cat; public java.lang.String getName(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #41 // Field name:Ljava/lang/String; 4: areturn LineNumberTable: line 14: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/example/jacoco/Cat;}SourceFile: "Cat.java"
紧接着魔数的4个字节是Class文件版本号,版本号又分为:
这个的版本号是随着jdk版本的不同而表示不同的版本范围的。Java的版本号是从45开始的。如果Class文件的版本号超过虚拟机版本,将被拒绝执行。
0X0034(对应十进制的50):JDK1.8
0X0033(对应十进制的50):JDK1.7 0X0032(对应十进制的50):JDK1.6 0X0031(对应十进制的49):JDK1.5 0X0030(对应十进制的48):JDK1.4 0X002F(对应十进制的47):JDK1.3 0X002E(对应十进制的46):JDK1.2 ps:0X表示16进制Java代码在进行Java编译的时候,并不像C和C++那样有"连接"这一步骤,而是在虚拟机加载Class文件的时候进行动态连接。也就是说,在Class文件中不会保存各个方法和字段的最终内存布局信息,因此这些字段和方法的符号引用不经过转换的话是无法被虚拟机使用的。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析并翻译到具体的内存地址之中。
紧接着魔数与版本号之后的是常量池入口.常量池简单理解为class文件的资源从库
常量池之中主要存放两大类常量:
符号引用: 属于编译原理方面的概念,包括了下面三类常量:
在常量池结束之后,紧接着的两个字节代表訪问标志。用于识别一些类或者接口层次的访问信息。例如以下表所看到的:
依据上面的表格,Cat.java的访问标志0x0021= 0x0001 | 0x0020 =ACC_PUBLIC | ACC_SUPER
如示例中的
0001 -- this class index0003 -- super class index0001 -- interface count0005 -- interfaces index
字段修饰符放在access_flags中,占2字节。
name index表示的16进制的值为指向常量池的某一项常量,代表的字段的名称
代表着字段的描述符。描述符的作用是用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值。
在descriptor_index之后会跟随0-n项额外信息,详见属性表
如示例中的
0002 -- feild count0009 -- access flag:public static 0007 -- name index:type0008 -- descript index: Ljava/lang/String;0000 -- attribute_info:00001 -- access flag:public 0009 -- name index:name0008 -- descript index: Ljava/lang/String;0000 -- attribute_info:0
0004 -- method count0008 -- access flag000a -- name index000b -- descript index0001 -- attributes count
在Class文件、字段表和方法表都可以携带自己的属性信息,这个信息用属性表进行描述,用于描述某些场景专有的信息。
与Class文件中其它数据项对长度、顺序、格式的严格要求不同,属性表集合不要求其中包含的属性表具有严格的顺序,并且只要属性的名称不与已有的属性名称重复,任何人实现的编译器可以向属性表中写入自己定义的属性信息。虚拟机在运行时会忽略不能识别的属性,为了能正确解析Class文件,虚拟机规范中预定义了虚拟机实现必须能够识别的9项属性(预定义属性已经增加到21项)
对于每个属性,它的名称需要从常量池中引用一个CONSTANT_utf8_info类型的常量类表示,而属性值的结构则是完全自定义的,只需要通过一个u4的长度属性区说明属性值所占用的位数即可.
Java程序方法体中的代码经过Javac编译处理后,最终变为字节码指令存储在Code属性中.Code属性出现在方法表的属性集合中,但是并非所有的方法表都有这个属性.例如接口或类中的方法就不存在Code属性了.在字节码指令之后的是方法的是方法的显式异常处理表集合,异常表对于Code属性来说并不是必须参在的.
这里的Exceptions属性是在方法表与Code属性平级的一项属性。Exceptions属性的作用是列举出方法中可能抛出的受查异常(Checked Exceptions),也就是说方法描述时在throws关键字啊后面列举的异常。他的结构见下表。Exceptions属性中的number_of_exceptions项表示方法可能抛出number_of_exceptions种受查异常,每一种受查异常使用一个exception_index_table项表示,exception_index_table是一个指向常量池中CONSTANT_Class_info型常量的索引,代表了该受查异常的类型。
LineNumberTable是Code属性中的一个子属性,用来描述java源文件行号与字节码文件偏移量之间的对应关系。当程序运行抛出异常时,异常堆栈中显示出错的行号就是根据这个对应关系来显示的,它的结构如下:
也是Code属性中的一个子属性,用来描述栈帧的局部变量表中变量与java源码中变量的对应关系,其结构如下:
其中local_variable_info结构如下:
参考
如示例中的
0004 -- method count0008 -- access flag000a -- name index:000b -- descript index0001 -- attributes count000c -- attribute_name_index : 对应Code属性0000 0026 -- attribute_length:38个字节0001 -- max_stack0000 -- max_locals0000 0006 -- code_length120d b300 0fb1 -- code:指令0000 -- exception_table_length0002 -- attributes_count0011 -- attribute_name_index:LineNumberTable0000 0006 -- line_number_table_length0001 -- line_number_table0000 -- start_pc:字节码偏移量0004 -- line_number:java源文件行号0012 -- attribute_name_index:LocalVariableTable0000 0002 -- attribute_length0000 -- local_variable_table_length0001 -- access flag0013 -- name index: 000b -- descript index0001 -- attributes count000c -- attribute_name_index : 对应Code属性0000 002f -- attribute_length:47个字节0001 -- max_stack 0001 -- max_locals 0000 0005 -- code_length 2ab7 0014 b1 -- code:指令0000 -- exception_table_length0002 -- attributes_count0011 -- attribute_name_index:LineNumberTable0000 0006 -- line_number_table_length0001 -- line_number_table0000 -- start_pc:字节码偏移量0003 -- line_number:java源文件行号0012 -- attribute_name_index:LocalVariableTable0000 000c -- attribute_length0001 -- local_variable_table_length0000 -- start_pc0005 -- length0016 -- name_index0017 -- descriptor_index0000 -- index000100 1800 0b00 0100 0c00 0000 3700 02000100 0000 09b2 0019 121f b600 21b1 00000002 0011 0000 000a 0002 0000 0009 0008000b 0012 0000 000c 0001 0000 0009 00160017 0000 0001 0027 0028 0001 000c 0000002f 0001 0001 0000 0005 2ab4 0029 b0000000 0200 1100 0000 0600 0100 0000 0e001200 0000 0c00 0100 0000 0500 1600 17000000 0100 2b00 0000 0200 2c
参考:
参考:转载地址:http://ewuwa.baihongyu.com/