记一次class字节码分析

本文深入解析了Java类文件的结构,包括类文件的基本格式、常量池信息、字段信息、方法信息及属性信息等关键部分,并通过具体示例详细解释了如何手动分析一个Java类文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#类源码

package com.zgx.test;

public class TestMainBase implements Comparable<Object>{

	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	public static void main(String[] args) {
		System.out.println("**class**");
	}

}

-------------------------------------------------------------------------------分割线-----------------------------------------------------------------------------------

#class文件的十六进制

Offset      0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15

00000000   CA FE BA BE 00 00 00 34  00 23 0A 00 06 00 14 09   漱壕   4 #      
00000016   00 15 00 16 08 00 17 0A  00 18 00 19 07 00 1A 07                   
00000032   00 1B 07 00 1C 01 00 06  3C 69 6E 69 74 3E 01 00           <init>  
00000048   03 28 29 56 01 00 04 43  6F 64 65 01 00 0F 4C 69    ()V   Code   Li
00000064   6E 65 4E 75 6D 62 65 72  54 61 62 6C 65 01 00 09   neNumberTable   
00000080   63 6F 6D 70 61 72 65 54  6F 01 00 15 28 4C 6A 61   compareTo   (Lja
00000096   76 61 2F 6C 61 6E 67 2F  4F 62 6A 65 63 74 3B 29   va/lang/Object;)
00000112   49 01 00 04 6D 61 69 6E  01 00 16 28 5B 4C 6A 61   I   main   ([Lja
00000128   76 61 2F 6C 61 6E 67 2F  53 74 72 69 6E 67 3B 29   va/lang/String;)
00000144   56 01 00 09 53 69 67 6E  61 74 75 72 65 01 00 3C   V   Signature  <
00000160   4C 6A 61 76 61 2F 6C 61  6E 67 2F 4F 62 6A 65 63   Ljava/lang/Objec
00000176   74 3B 4C 6A 61 76 61 2F  6C 61 6E 67 2F 43 6F 6D   t;Ljava/lang/Com
00000192   70 61 72 61 62 6C 65 3C  4C 6A 61 76 61 2F 6C 61   parable<Ljava/la
00000208   6E 67 2F 4F 62 6A 65 63  74 3B 3E 3B 01 00 0A 53   ng/Object;>;   S
00000224   6F 75 72 63 65 46 69 6C  65 01 00 11 54 65 73 74   ourceFile   Test
00000240   4D 61 69 6E 42 61 73 65  2E 6A 61 76 61 0C 00 08   MainBase.java   
00000256   00 09 07 00 1D 0C 00 1E  00 1F 01 00 09 2A 2A 63                **c
00000272   6C 61 73 73 2A 2A 07 00  20 0C 00 21 00 22 01 00   lass**     ! "  
00000288   19 63 6F 6D 2F 7A 67 78  2F 74 65 73 74 2F 54 65    com/zgx/test/Te
00000304   73 74 4D 61 69 6E 42 61  73 65 01 00 10 6A 61 76   stMainBase   jav
00000320   61 2F 6C 61 6E 67 2F 4F  62 6A 65 63 74 01 00 14   a/lang/Object   
00000336   6A 61 76 61 2F 6C 61 6E  67 2F 43 6F 6D 70 61 72   java/lang/Compar
00000352   61 62 6C 65 01 00 10 6A  61 76 61 2F 6C 61 6E 67   able   java/lang
00000368   2F 53 79 73 74 65 6D 01  00 03 6F 75 74 01 00 15   /System   out   
00000384   4C 6A 61 76 61 2F 69 6F  2F 50 72 69 6E 74 53 74   Ljava/io/PrintSt
00000400   72 65 61 6D 3B 01 00 13  6A 61 76 61 2F 69 6F 2F   ream;   java/io/
00000416   50 72 69 6E 74 53 74 72  65 61 6D 01 00 07 70 72   PrintStream   pr
00000432   69 6E 74 6C 6E 01 00 15  28 4C 6A 61 76 61 2F 6C   intln   (Ljava/l
00000448   61 6E 67 2F 53 74 72 69  6E 67 3B 29 56 00 21 00   ang/String;)V ! 
00000464   05 00 06 00 01 00 07 00  00 00 03 00 01 00 08 00                   
00000480   09 00 01 00 0A 00 00 00  1D 00 01 00 01 00 00 00                   
00000496   05 2A B7 00 01 B1 00 00  00 01 00 0B 00 00 00 06    *? ?         
00000512   00 01 00 00 00 03 00 01  00 0C 00 0D 00 01 00 0A                   
00000528   00 00 00 1A 00 01 00 02  00 00 00 02 03 AC 00 00                ? 
00000544   00 01 00 0B 00 00 00 06  00 01 00 00 00 08 00 09                   
00000560   00 0E 00 0F 00 01 00 0A  00 00 00 25 00 02 00 01              %    
00000576   00 00 00 09 B2 00 02 12  03 B6 00 04 B1 00 00 00       ?   ? ?  
00000592   01 00 0B 00 00 00 0A 00  02 00 00 00 0B 00 08 00                   
00000608   0C 00 02 00 10 00 00 00  02 00 11 00 12 00 00 00                   
00000624   02 00 13   
                                   
-------------------------------------------------------------------------------分割线-----------------------------------------------------------------------------------
#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];
}



-------------------------------------------------------------------------------分割线-----------------------------------------------------------------------------------

#常量池信息,左边数字为十进制的tag值,右边为16进制的tag值,每个tag值对应着一类常量


1:  CONSTANT_Utf8_info { u1 tag;u2 length;u1 bytes[length];} 	u1+u2+u1[length] 01	

3:  CONSTANT_Integer_info { u1 tag;u4 bytes;}					u1+u4		 	 03	

4:  CONSTANT_Float_info { u1 tag;u4 bytes;}						u1+u4		 	 04		

5:  CONSTANT_Long_info { u1 tag;u4 high_bytes;u4 low_bytes;}	u1+u4+u4	     05	

6:  CONSTANT_Double_info { u1 tag;u4 high_bytes;u4 low_bytes;}	u1+u4+u4		 06	


7:  CONSTANT_Class_info { u1 tag;u2 name_index;}				u1+u2		 	 07		

8:  CONSTANT_String_info { u1 tag;u2 string_index;}				u1+u2 		     08		


9:  CONSTANT_Fieldref_info { u1 tag;u2 class_index;				u1+u2+u2  	     09
	u2 name_and_type_index;}

10: CONSTANT_Methodref_info { u1 tag;u2 class_index;			u1+u2+u2 	     0A
 	u2 name_and_type_index;}

11: CONSTANT_InterfaceMethodref_info { u1 tag;					u1+u2+u2 	     0B
 	u2 class_index;u2 name_and_type_index;}


12: CONSTANT_NameAndType_info { u1 tag;u2 name_index;			u1+u2+u2		 0C
 	u2 descriptor_index;}

15: CONSTANT_MethodHandle_info { u1 tag;u1 reference_kind;		u1+u1+u2	     0F
 	u2 reference_index;}


16: CONSTANT_MethodType_info { u1 tag;u2 descriptor_index;}		u1+u2 			 10


18: CONSTANT_InvokeDynamic_info { u1 tag;
	u2 bootstrap_method_attr_index;u2 name_and_type_index;} 	u1+u2+u2	 	 12


+++++++++++++++++++++++++++++Java SE9 新加常量+++++++++++++++++++++++++++++++++++++
19: CONSTANT_Module_info { u1 tag;u2 name_index;}				u1+u2		   	 13

20: CONSTANT_Package_info { u1 tag;u2 name_index;}				u1+u2	 	 	 14



-------------------------------------------------------------------------------分割线-----------------------------------------------------------------------------------
#字段信息


field_info {
 u2 access_flags;
 u2 name_index;
 u2 descriptor_index;
 u2 attributes_count;
 attribute_info attributes[attributes_count];
}

#方法信息

method_info {
 u2 access_flags;
 u2 name_index;
 u2 descriptor_index;
 u2 attributes_count;
 attribute_info attributes[attributes_count];
}

#属性信息


attribute_info {
 u2 attribute_name_index;
 u4 attribute_length;
 u1 info[attribute_length];
}

#字节码属性

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];
}


-------------------------------------------------------------------------------分割线-----------------------------------------------------------------------------------

#手动分析class文件

CA FE BA BE		魔数 			u4 		magic;
00 00			次版本号		u2 		minor_version;
00 34 			主版本号		u2 		major_version;
00 23 			常量池大小		u2 		constant_pool_count;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&常量池分析&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1	0A 00 06 00 14		方法的符号引用			u1+u2+u2 		 CONSTANT_Methodref_info
2	09 00 15 00 16		字段引用				u1+u2+u2 		 CONSTANT_Fieldref_info
3	08 00 17			字符串类型字面量		u1+u2 			 CONSTANT_String_info
4	0A 00 18 00 19		方法的符号引用			u1+u2+u2 		 CONSTANT_Methodref_info
5	07 00 1A			类或接口的符号引用		u1+u2			 CONSTANT_Class_info
6	07 00 1B
7	07 00 1C
8	01 00 06  3C 69 6E 69 74 3E
9	01 00 03 28 29 56	UTF-8编码字符串		u1+u2+u1[length] CONSTANT_Utf8_info
10	01 00 04 43 6F 64 65
11	01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72  54 61 62 6C 65
12	01 00 09 63 6F 6D 70 61 72 65 54 6F
13	01 00 15 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F  4F 62 6A 65 63 74 3B 29 49 
14	01 00 04 6D 61 69 6E
15	01 00 16 28 5B 4C 6A 61 76 61 2F 6C 61 6E 67 2F  53 74 72 69 6E 67 3B 29
16	01 00 09 53 69 67 6E  61 74 75 72 65
17	01 00 3C 4C 6A 61 76 61 2F 6C 61  6E 67 2F 4F 62 6A 65 63 74 3B 4C 6A 61 76 61 2F  6C 61 6E 67 2F 43 6F 6D 70 61 72 61 62 6C 65 3C  4C 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63  74 3B 3E 3B
18	01 00 0A 53 6F 75 72 63 65 46 69 6C  65
19	01 00 11 54 65 73 74 4D 61 69 6E 42 61 73 65  2E 6A 61 76 61
20	0C 00 08 00 09		
21	07 00 1D
22	0C 00 1E  00 1F
23	01 00 09 2A 2A 63 6C 61 73 73 2A 2A
24	07 00  20
25	0C 00 21 00 22 		字段或方法的部分符号引用	u1+u2+u2			CONSTANT_NameAndType_info	 
26	01 00 19 63 6F 6D 2F 7A 67 78  2F 74 65 73 74 2F 54 65 73 74 4D 61 69 6E 42 61  73 65
27	01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F  62 6A 65 63 74
28	01 00 14 6A 61 76 61 2F 6C 61 6E  67 2F 43 6F 6D 70 61 72 61 62 6C 65
29	01 00 10 6A  61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D
30	01  00 03 6F 75 74
31	01 00 15 4C 6A 61 76 61 2F 69 6F  2F 50 72 69 6E 74 53 74 72 65 61 6D 3B
32	01 00 13  6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72  65 61 6D
33	01 00 07 70 72 69 6E 74 6C 6E 
34	01 00 15  28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69  6E 67 3B 29 56
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&常量池分析结束&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
00 21			访问标识		u2		access_flags
00 05			类信息			u2		this_class
00 06			父类信息		u2		super_class
00 01			接口数量		u2		interfaces_count
00 07			接口			u2		interfaces[interfaces_count]
00 00			字段数			u2		fields_count
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&字段分析(类似方法分析)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
								field_info 	fields[fields_count]	##这里不存在
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&字段分析结束&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
00 03							u2		methods_count
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&方法分析(三个方法)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
00 01							u2		access_flag
00 08							u2		name_index
00 09							u2		descriptor_index
00 01							u2		attributes_count
*****************************************方法属性分析attribute_info************************************		
00 0A							u2		attribute_name_index
00 00 00  1D					u4		attribute_length
								u1 info[attribute_length]
00 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00 00 01 00 0B 00 00 00 06 00 01 00 00 00 03	
*****************方法属性分析结束(同时第一个方法分析结束,以下两个方法分析类似)**********************

00 01 
00 0C
00 0D
00 01

00 0A
00 00 00 1A
00 01 00 02  00 00 00 02 03 AC 00 00 00 01 00 0B 00 00 00 06  00 01 00 00 00 08

00 09
00 0E
00 0F
00 01

00 0A
00 00 00 25
00 02 00 01 00 00 00 09 B2 00 02 12  03 B6 00 04 B1 00 00 00 01 00 0B 00 00 00 0A 00  02 00 00 00 0B 00 08 00 0C

########################################对第三个方法进行Code属性分析#####################################
#  00 0A												u2 				attribute_name_index;			#
#  00 00 00 25											u4 				attribute_length;				#
#																										#
#  00 02												u2 				max_stack;						#
#  00 01												u2 				max_locals;						#	
#  00 00 00 09											u4 				code_length;					#
#  B2 00 02 12  03 B6 00 04 B1							u1 code[code_length]							#
#  00 00												u2 				exception_table_length;			#
#  00 01												u2 		attributes_count;						#
#  00 0B 00 00 00 0A 00  02 00 00 00 0B 00 08 00 0C		attribute_info attributes[attributes_count];	#
#																										#
########################################对第三个方法进行Code属性分析结束#################################

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&方法分析结束&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

00 02 						u2		attributes_count
========================================属性分析类似方法的属性分析=====================================
00 10						u2
00 00 00  02
00 11

00 12
00 00 00 02
00 13



-------------------------------------------------------------------------------分割线-----------------------------------------------------------------------------------

#javap -verbose 分析class文件
	

public class com.zgx.test.TestMainBase extends java.lang.Object implements java.lang.Comparable<java.lang.Object>
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#20         // java/lang/Object."<init>":()V
   #2 = Fieldref           #21.#22        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #23            // **class**
   #4 = Methodref          #24.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #26            // com/zgx/test/TestMainBase
   #6 = Class              #27            // java/lang/Object
   #7 = Class              #28            // java/lang/Comparable
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               compareTo
  #13 = Utf8               (Ljava/lang/Object;)I
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               Signature
  #17 = Utf8               Ljava/lang/Object;Ljava/lang/Comparable<Ljava/lang/Object;>;
  #18 = Utf8               SourceFile
  #19 = Utf8               TestMainBase.java
  #20 = NameAndType        #8:#9          // "<init>":()V
  #21 = Class              #29            // java/lang/System
  #22 = NameAndType        #30:#31        // out:Ljava/io/PrintStream;
  #23 = Utf8               **class**
  #24 = Class              #32            // java/io/PrintStream
  #25 = NameAndType        #33:#34        // println:(Ljava/lang/String;)V
  #26 = Utf8               com/zgx/test/TestMainBase
  #27 = Utf8               java/lang/Object
  #28 = Utf8               java/lang/Comparable
  #29 = Utf8               java/lang/System
  #30 = Utf8               out
  #31 = Utf8               Ljava/io/PrintStream;
  #32 = Utf8               java/io/PrintStream
  #33 = Utf8               println
  #34 = Utf8               (Ljava/lang/String;)V
{
  public com.zgx.test.TestMainBase();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public int compareTo(java.lang.Object);
    descriptor: (Ljava/lang/Object;)I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=2, args_size=2
         0: iconst_0
         1: ireturn
      LineNumberTable:
        line 8: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String **class**
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 11: 0
        line 12: 8
}
Signature: #17                          // Ljava/lang/Object;Ljava/lang/Comparable<Ljava/lang/Object;>;
SourceFile: "TestMainBase.java"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值