java class文件详解
来源:互联网 发布:mac需要清理软件 编辑:程序博客网 时间:2024/05/22 10:36
Java Class文件结构信息:
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]; //属性表}
1 代码实例:
地址: https://github.com/pantherproject/jvm-practice/tree/master/src/main/java/com/panther/jvm
用二进制打开文件:
hexdump -C Sub.class 00000000 ca fe ba be 00 00 00 34 00 3b 0a 00 0a 00 28 09 |.......4.;....(.|00000010 00 09 00 29 09 00 09 00 2a 09 00 09 00 2b 09 00 |...)....*....+..|00000020 2c 00 2d 08 00 2e 0a 00 2f 00 30 08 00 31 07 00 |,.-...../.0..1..|00000030 32 07 00 33 07 00 34 07 00 35 01 00 06 73 75 62 |2..3..4..5...sub|00000040 49 6e 74 01 00 01 49 01 00 09 73 75 62 53 74 72 |Int...I...subStr|00000050 69 6e 67 01 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 |ing...Ljava/lang|00000060 2f 53 74 72 69 6e 67 3b 01 00 09 73 75 62 4f 62 |/String;...subOb|00000070 6a 65 63 74 01 00 12 4c 6a 61 76 61 2f 6c 61 6e |ject...Ljava/lan|00000080 67 2f 4f 62 6a 65 63 74 3b 01 00 06 3c 69 6e 69 |g/Object;...<ini|00000090 74 3e 01 00 03 28 29 56 01 00 04 43 6f 64 65 01 |t>...()V...Code.|000000a0 00 0f 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c |..LineNumberTabl|000000b0 65 01 00 09 67 65 74 53 75 62 49 6e 74 01 00 03 |e...getSubInt...|000000c0 28 29 49 01 00 09 73 65 74 53 75 62 49 6e 74 01 |()I...setSubInt.|000000d0 00 04 28 49 29 56 01 00 0c 67 65 74 53 75 62 53 |..(I)V...getSubS|000000e0 74 72 69 6e 67 01 00 14 28 29 4c 6a 61 76 61 2f |tring...()Ljava/|000000f0 6c 61 6e 67 2f 53 74 72 69 6e 67 3b 01 00 0c 73 |lang/String;...s|00000100 65 74 53 75 62 53 74 72 69 6e 67 01 00 15 28 4c |etSubString...(L|00000110 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 |java/lang/String|00000120 3b 29 56 01 00 0c 67 65 74 53 75 62 4f 62 6a 65 |;)V...getSubObje|00000130 63 74 01 00 14 28 29 4c 6a 61 76 61 2f 6c 61 6e |ct...()Ljava/lan|00000140 67 2f 4f 62 6a 65 63 74 3b 01 00 0c 73 65 74 53 |g/Object;...setS|00000150 75 62 4f 62 6a 65 63 74 01 00 15 28 4c 6a 61 76 |ubObject...(Ljav|00000160 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 3b 29 56 |a/lang/Object;)V|00000170 01 00 06 69 6e 74 65 72 43 01 00 06 69 6e 74 65 |...interC...inte|00000180 72 42 01 00 15 28 49 29 4c 6a 61 76 61 2f 6c 61 |rB...(I)Ljava/la|00000190 6e 67 2f 53 74 72 69 6e 67 3b 01 00 0a 53 6f 75 |ng/String;...Sou|000001a0 72 63 65 46 69 6c 65 01 00 08 53 75 62 2e 6a 61 |rceFile...Sub.ja|000001b0 76 61 0c 00 13 00 14 0c 00 0d 00 0e 0c 00 0f 00 |va..............|000001c0 10 0c 00 11 00 12 07 00 36 0c 00 37 00 38 01 00 |........6..7.8..|000001d0 11 74 68 65 20 69 6e 74 65 72 43 20 69 6e 20 53 |.the interC in S|000001e0 75 62 07 00 39 0c 00 3a 00 1e 01 00 11 74 68 65 |ub..9..:.....the|000001f0 20 69 6e 74 65 72 42 20 69 6e 20 53 75 62 01 00 | interB in Sub..|00000200 13 63 6f 6d 2f 70 61 6e 74 68 65 72 2f 6a 76 6d |.com/panther/jvm|00000210 2f 53 75 62 01 00 14 63 6f 6d 2f 70 61 6e 74 68 |/Sub...com/panth|00000220 65 72 2f 6a 76 6d 2f 42 61 73 65 01 00 16 63 6f |er/jvm/Base...co|00000230 6d 2f 70 61 6e 74 68 65 72 2f 6a 76 6d 2f 49 6e |m/panther/jvm/In|00000240 74 65 72 42 01 00 16 63 6f 6d 2f 70 61 6e 74 68 |terB...com/panth|00000250 65 72 2f 6a 76 6d 2f 49 6e 74 65 72 43 01 00 10 |er/jvm/InterC...|00000260 6a 61 76 61 2f 6c 61 6e 67 2f 53 79 73 74 65 6d |java/lang/System|00000270 01 00 03 6f 75 74 01 00 15 4c 6a 61 76 61 2f 69 |...out...Ljava/i|00000280 6f 2f 50 72 69 6e 74 53 74 72 65 61 6d 3b 01 00 |o/PrintStream;..|00000290 13 6a 61 76 61 2f 69 6f 2f 50 72 69 6e 74 53 74 |.java/io/PrintSt|000002a0 72 65 61 6d 01 00 07 70 72 69 6e 74 6c 6e 00 21 |ream...println.!|000002b0 00 09 00 0a 00 02 00 0b 00 0c 00 03 00 02 00 0d |................|000002c0 00 0e 00 00 00 0a 00 0f 00 10 00 00 00 0a 00 11 |................|000002d0 00 12 00 00 00 09 00 01 00 13 00 14 00 01 00 15 |................|000002e0 00 00 00 1d 00 01 00 01 00 00 00 05 2a b7 00 01 |............*...|000002f0 b1 00 00 00 01 00 16 00 00 00 06 00 01 00 00 00 |................|00000300 06 00 01 00 17 00 18 00 01 00 15 00 00 00 1d 00 |................|00000310 01 00 01 00 00 00 05 2a b4 00 02 ac 00 00 00 01 |.......*........|00000320 00 16 00 00 00 06 00 01 00 00 00 0f 00 01 00 19 |................|00000330 00 1a 00 01 00 15 00 00 00 22 00 02 00 02 00 00 |........."......|00000340 00 06 2a 1b b5 00 02 b1 00 00 00 01 00 16 00 00 |..*.............|00000350 00 0a 00 02 00 00 00 13 00 05 00 14 00 09 00 1b |................|00000360 00 1c 00 01 00 15 00 00 00 1c 00 01 00 00 00 00 |................|00000370 00 04 b2 00 03 b0 00 00 00 01 00 16 00 00 00 06 |................|00000380 00 01 00 00 00 17 00 09 00 1d 00 1e 00 01 00 15 |................|00000390 00 00 00 21 00 01 00 01 00 00 00 05 2a b3 00 03 |...!........*...|000003a0 b1 00 00 00 01 00 16 00 00 00 0a 00 02 00 00 00 |................|000003b0 1b 00 04 00 1c 00 09 00 1f 00 20 00 01 00 15 00 |.......... .....|000003c0 00 00 1c 00 01 00 00 00 00 00 04 b2 00 04 b0 00 |................|000003d0 00 00 01 00 16 00 00 00 06 00 01 00 00 00 1f 00 |................|000003e0 09 00 21 00 22 00 01 00 15 00 00 00 21 00 01 00 |..!.".......!...|000003f0 01 00 00 00 05 2a b3 00 04 b1 00 00 00 01 00 16 |.....*..........|00000400 00 00 00 0a 00 02 00 00 00 23 00 04 00 24 00 01 |.........#...$..|00000410 00 23 00 14 00 01 00 15 00 00 00 25 00 02 00 01 |.#.........%....|00000420 00 00 00 09 b2 00 05 12 06 b6 00 07 b1 00 00 00 |................|00000430 01 00 16 00 00 00 0a 00 02 00 00 00 28 00 08 00 |............(...|00000440 29 00 01 00 24 00 25 00 01 00 15 00 00 00 1b 00 |)...$.%.........|00000450 01 00 02 00 00 00 03 12 08 b0 00 00 00 01 00 16 |................|00000460 00 00 00 06 00 01 00 00 00 2d 00 01 00 26 00 00 |.........-...&..|00000470 00 02 00 27 |...'|00000474
2. 魔数
作用:确定该文件是否是虚拟机可接受的class文件。java的魔数统一为 0xCAFEBABE (来源于一款咖啡)。
区域:文件第0~3字节。
3. 版本号
作用:表示class文件的版本,由minorversion和majorversion组成。
区域:文件第4~7字节。51代表,jdk为1.7.0
需要注意的是java版本号是从45开始的,大版本发布,主版本号+1.高版本的jdk能向下兼容以前版本的class文件,但不兼容以后版本的class文件4. 常量池
常量池的大小是不固定的,根据你的类中的常量的多少而定,所以在常量池的入口,放置了一个u2类型的表示常量池中常量个数的常量池容量计数器。计数器从1开始,第0位有特殊含义,表示指向常量池的索引值数据不引用任何一个常量池项目。池中的数据项就像数组一样是通过索引访问的。
我们可以清楚的看到,我们常量池中有63-1=62个常量。这些常量是什么呢?
要存放字面量Literal和符号引用Symbolic References。
字面量可能是文本字符串,或final的常量值。
符号引用包括以下:
- 类或接口全限定名 Full Qualified Name
- 字段名称和描述符 Descriptor
- 方法名称和描述符
我们使用反编译工具查看一下:
javap -v Sub.class Classfile /opt/soft/project/54/jvm-practice/src/main/java/com/panther/jvm/Sub.class Last modified 2017-8-23; size 1140 bytes MD5 checksum e07ec896433041cc874ab7adabd1c7ac Compiled from "Sub.java"public class com.panther.jvm.Sub extends com.panther.jvm.Base implements com.panther.jvm.InterB,com.panther.jvm.InterC minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Methodref #10.#40 // com/panther/jvm/Base."<init>":()V #2 = Fieldref #9.#41 // com/panther/jvm/Sub.subInt:I #3 = Fieldref #9.#42 // com/panther/jvm/Sub.subString:Ljava/lang/String; #4 = Fieldref #9.#43 // com/panther/jvm/Sub.subObject:Ljava/lang/Object; #5 = Fieldref #44.#45 // java/lang/System.out:Ljava/io/PrintStream; #6 = String #46 // the interC in Sub #7 = Methodref #47.#48 // java/io/PrintStream.println:(Ljava/lang/String;)V #8 = String #49 // the interB in Sub #9 = Class #50 // com/panther/jvm/Sub #10 = Class #51 // com/panther/jvm/Base #11 = Class #52 // com/panther/jvm/InterB #12 = Class #53 // com/panther/jvm/InterC #13 = Utf8 subInt #14 = Utf8 I #15 = Utf8 subString #16 = Utf8 Ljava/lang/String; #17 = Utf8 subObject #18 = Utf8 Ljava/lang/Object; #19 = Utf8 <init> #20 = Utf8 ()V #21 = Utf8 Code #22 = Utf8 LineNumberTable #23 = Utf8 getSubInt #24 = Utf8 ()I #25 = Utf8 setSubInt #26 = Utf8 (I)V #27 = Utf8 getSubString #28 = Utf8 ()Ljava/lang/String; #29 = Utf8 setSubString #30 = Utf8 (Ljava/lang/String;)V #31 = Utf8 getSubObject #32 = Utf8 ()Ljava/lang/Object; #33 = Utf8 setSubObject #34 = Utf8 (Ljava/lang/Object;)V #35 = Utf8 interC #36 = Utf8 interB #37 = Utf8 (I)Ljava/lang/String; #38 = Utf8 SourceFile #39 = Utf8 Sub.java #40 = NameAndType #19:#20 // "<init>":()V #41 = NameAndType #13:#14 // subInt:I #42 = NameAndType #15:#16 // subString:Ljava/lang/String; #43 = NameAndType #17:#18 // subObject:Ljava/lang/Object; #44 = Class #54 // java/lang/System #45 = NameAndType #55:#56 // out:Ljava/io/PrintStream; #46 = Utf8 the interC in Sub #47 = Class #57 // java/io/PrintStream #48 = NameAndType #58:#30 // println:(Ljava/lang/String;)V #49 = Utf8 the interB in Sub #50 = Utf8 com/panther/jvm/Sub #51 = Utf8 com/panther/jvm/Base #52 = Utf8 com/panther/jvm/InterB #53 = Utf8 com/panther/jvm/InterC #54 = Utf8 java/lang/System #55 = Utf8 out #56 = Utf8 Ljava/io/PrintStream; #57 = Utf8 java/io/PrintStream #58 = Utf8 println{ public com.panther.jvm.Sub(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method com/panther/jvm/Base."<init>":()V 4: return LineNumberTable: line 6: 0 public int getSubInt(); descriptor: ()I flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #2 // Field subInt:I 4: ireturn LineNumberTable: line 15: 0 public void setSubInt(int); descriptor: (I)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: iload_1 2: putfield #2 // Field subInt:I 5: return LineNumberTable: line 19: 0 line 20: 5 public static java.lang.String getSubString(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=0, args_size=0 0: getstatic #3 // Field subString:Ljava/lang/String; 3: areturn LineNumberTable: line 23: 0 public static void setSubString(java.lang.String); descriptor: (Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: putstatic #3 // Field subString:Ljava/lang/String; 4: return LineNumberTable: line 27: 0 line 28: 4 public static java.lang.Object getSubObject(); descriptor: ()Ljava/lang/Object; flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=0, args_size=0 0: getstatic #4 // Field subObject:Ljava/lang/Object; 3: areturn LineNumberTable: line 31: 0 public static void setSubObject(java.lang.Object); descriptor: (Ljava/lang/Object;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: putstatic #4 // Field subObject:Ljava/lang/Object; 4: return LineNumberTable: line 35: 0 line 36: 4 public void interC(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #6 // String the interC in Sub 5: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return LineNumberTable: line 40: 0 line 41: 8 public java.lang.String interB(int); descriptor: (I)Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: ldc #8 // String the interB in Sub 2: areturn LineNumberTable: line 45: 0}SourceFile: "Sub.java"
常量池中的项目类型如下:
- CONSTANT_Utf8_info tag标志位为1, UTF-8编码的字符串
- CONSTANT_Integer_info tag标志位为3, 整形字面量
- CONSTANT_Float_info tag标志位为4, 浮点型字面量
- CONSTANT_Long_info tag标志位为5, 长整形字面量
- CONSTANT_Double_info tag标志位为6, 双精度字面量
- CONSTANT_Class_info tag标志位为7, 类或接口的符号引用
- CONSTANT_String_info tag标志位为8,字符串类型的字面量
- CONSTANT_Fieldref_info tag标志位为9, 字段的符号引用
- CONSTANT_Methodref_info tag标志位为10,类中方法的符号引用
- CONSTANT_InterfaceMethodref_info tag标志位为11, 接口中方法的符号引用
- CONSTANT_NameAndType_info tag 标志位为12,字段和方法的名称以及类型的符号引用
5. 类或接口访问标志
表示类或者接口方面的访问信息,比如Class表示的是类还是接口,是否为public、static、final等。,下面我们就来看看TestClass的访问标示。Class的访问标志值为0x0021:
根据前面说的各种访问标示的标志位,我们可以知道:0x0021=0x0001|0x0020 也即ACC_PUBLIC 和 ACC_SUPER为真,其中ACC_PUBLIC大家好理解,ACC_SUPER是jdk1.2之后编译的类都会带有的标志。
- Java Class文件详解
- java .class文件详解
- Java Class文件详解
- Java Class文件详解
- java class文件详解
- Java 中Class文件详解
- java源文件和class文件编码详解
- java底层知识(1)--Class文件详解
- 运行java的class文件方法详解
- 运行java的class文件方法详解
- Java虚拟机(一)-Java的class文件详解
- Class文件详解 (1)
- Class文件详解 (2)
- Class文件详解 (1)
- Class文件详解 (2)
- Class文件详解
- Class文件详解 (1)
- Class文件详解 (1)
- CentOS7 opencv3.2.0 安装
- ImageLoader_下载图片并缓存
- 干货 | 算法工程师入门第三期——黄李超讲物体检测
- Python中变量赋值传递时的引用和拷贝
- SQL必知必会(7)——使用子查询
- java class文件详解
- 权限管理以及shiro的简述(个人理解)
- Linux中的文件夹操作命令
- 在jqGrid中新增、删除、编辑等操作按钮
- HashMap什么时候重写hashcode和equals方法,为什么需要重写
- 【云计算的1024种玩法】为喜欢的人建一个网站
- $.get、$.post、$getJSON、$ajax的用法跟区别
- IO 全面解释
- activiti与spring整合