//接口
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 0016
636f 6d2f 6578 616d 706c 652f 6a61 636f
636f 2f43 6174 0700 0401 0010 6a61 7661
2f6c 616e 672f 4f62 6a65 6374 0700 0601
0019 636f 6d2f 6578 616d 706c 652f 6a61
636f 636f 2f41 6e69 6d61 6c01 0004 7479
7065 0100 124c 6a61 7661 2f6c 616e 672f
5374 7269 6e67 3b01 0004 6e61 6d65 0100
083c 636c 696e 6974 3e01 0003 2829 5601
0004 436f 6465 0800 0e01 0003 6361 7409
0001 0010 0c00 0700 0801 000f 4c69 6e65
4e75 6d62 6572 5461 626c 6501 0012 4c6f
6361 6c56 6172 6961 626c 6554 6162 6c65
0100 063c 696e 6974 3e0a 0003 0015 0c00
1300 0b01 0004 7468 6973 0100 184c 636f
6d2f 6578 616d 706c 652f 6a61 636f 636f
2f43 6174 3b01 0003 6561 7409 001a 001c
0700 1b01 0010 6a61 7661 2f6c 616e 672f
5379 7374 656d 0c00 1d00 1e01 0003 6f75
7401 0015 4c6a 6176 612f 696f 2f50 7269
6e74 5374 7265 616d 3b08 0020 0100 192d
2d2d 2d2d 2d2d 2d2d 2d2d 6561 742d 2d2d
2d2d 2d2d 2d2d 2d2d 0a00 2200 2407 0023
0100 136a 6176 612f 696f 2f50 7269 6e74
5374 7265 616d 0c00 2500 2601 0007 7072
696e 746c 6e01 0015 284c 6a61 7661 2f6c
616e 672f 5374 7269 6e67 3b29 5601 0007
6765 744e 616d 6501 0014 2829 4c6a 6176
612f 6c61 6e67 2f53 7472 696e 673b 0900
0100 2a0c 0009 0008 0100 0a53 6f75 7263
6546 696c 6501 0008 4361 742e 6a61 7661
0021 0001 0003 0001 0005 0002 0009 0007
0008 0000 0001 0009 0008 0000 0004 0008
000a 000b 0001 000c 0000 0026 0001 0000
0000 0006 120d b300 0fb1 0000 0002 0011
0000 0006 0001 0000 0004 0012 0000 0002
0000 0001 0013 000b 0001 000c 0000 002f
0001 0001 0000 0005 2ab7 0014 b100 0000
0200 1100 0000 0600 0100 0000 0300 1200
0000 0c00 0100 0000 0500 1600 1700 0000
0100 1800 0b00 0100 0c00 0000 3700 0200
0100 0000 09b2 0019 121f b600 21b1 0000
0002 0011 0000 000a 0002 0000 0009 0008
000b 0012 0000 000c 0001 0000 0009 0016
0017 0000 0001 0027 0028 0001 000c 0000
002f 0001 0001 0000 0005 2ab4 0029 b000
0000 0200 1100 0000 0600 0100 0000 0e00
1200 0000 0c00 0100 0000 0500 1600 1700
0000 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_SUPER
Constant 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 index
0003 -- super class index
0001 -- interface count
0005 -- interfaces index
name index表示的16进制的值为指向常量池的某一项常量,代表的字段的名称
代表着字段的描述符。描述符的作用是用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值。
在descriptor_index之后会跟随0-n项额外信息,详见属性表
如示例中的
0002 -- feild count
0009 -- access flag:public static
0007 -- name index:type
0008 -- descript index: Ljava/lang/String;
0000 -- attribute_info:0
0001 -- access flag:public
0009 -- name index:name
0008 -- descript index: Ljava/lang/String;
0000 -- attribute_info:0
0004 -- method count
0008 -- access flag
000a -- name index
000b -- descript index
0001 -- 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源码中变量的对应关系,其结构如下:
参考https://blog.csdn.net/qq_35892775/article/details/85860479
如示例中的
0004 -- method count
0008 -- access flag
000a -- name index:
000b -- descript index
0001 -- attributes count
000c -- attribute_name_index : 对应Code属性
0000 0026 -- attribute_length:38个字节
0001 -- max_stack
0000 -- max_locals
0000 0006 -- code_length
120d b300 0fb1 -- code:指令
0000 -- exception_table_length
0002 -- attributes_count
0011 -- attribute_name_index:LineNumberTable
0000 0006 -- line_number_table_length
0001 -- line_number_table
0000 -- start_pc:字节码偏移量
0004 -- line_number:java源文件行号
0012 -- attribute_name_index:LocalVariableTable
0000 0002 -- attribute_length
0000 -- local_variable_table_length
0001 -- access flag
0013 -- name index:
000b -- descript index
0001 -- attributes count
000c -- 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_length
0002 -- attributes_count
0011 -- attribute_name_index:LineNumberTable
0000 0006 -- line_number_table_length
0001 -- line_number_table
0000 -- start_pc:字节码偏移量
0003 -- line_number:java源文件行号
0012 -- attribute_name_index:LocalVariableTable
0000 000c -- attribute_length
0001 -- local_variable_table_length
0000 -- start_pc
0005 -- length
0016 -- name_index
0017 -- descriptor_index
0000 -- index
00
0100 1800 0b00 0100 0c00 0000 3700 0200
0100 0000 09b2 0019 121f b600 21b1 0000
0002 0011 0000 000a 0002 0000 0009 0008
000b 0012 0000 000c 0001 0000 0009 0016
0017 0000 0001 0027 0028 0001 000c 0000
002f 0001 0001 0000 0005 2ab4 0029 b000
0000 0200 1100 0000 0600 0100 0000 0e00
1200 0000 0c00 0100 0000 0500 1600 1700
0000 0100 2b00 0000 0200 2c
参考:https://blog.csdn.net/github_35983163/article/details/52945845
参考:http://www.blogjava.net/DLevin/archive/2011/09/05/358033.html