Java class 文件简介

 

Java class 文件时对Java程序二进制文件格式的精确定义。

一个class文件只能包含一个类或接口。

Java class文件是8位字节的二进制流。

在Java class文件中,可变长度项的大小和长度位于其实际数据之前。

class文件的基本类型

  u1  1byte   无符号类型

  u2  2byte  无符号类型

  u4  4byte   无符号类型

  u8  8byte  无符号类型

=============================================================================================================================

以下是Java源码文件

public class ClassTest {
    final static int constantInt=12;
    final static String  constantString="我很好";
    static int variableInt=12;
    static String  variableString="我很好";
    private int variable;
    private String variable2;

    public static void main(String[] args) {
        System.out.println("--这是main()方法---");

    }
    public void say() {
        System.out.println("这是普通方法");
    }
    public ClassTest(int variable, String variable2) {
        super();
        this.variable = variable;
        this.variable2 = variable2;
    }
    public ClassTest() {
        
    }
View Code

以下是使用uedit 编辑器查看的字节码文件

  

以下是使用 javap -v ClssTest.class  查看的字节码文件内容 

 Last modified 2019-7-24; size 924 bytes
  MD5 checksum be5b20653620d7d2b495a3f99e3fb417
  Compiled from "ClassTest.java"
public class ClassTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Fieldref           #34.#35        // java/lang/System.out:Ljava/io/PrintStream;
   #2 = String             #36            // --这是main()方法---
   #3 = Methodref          #37.#38        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #4 = String             #39            // 这是普通方法
   #5 = Methodref          #12.#40        // java/lang/Object."<init>":()V
   #6 = Fieldref           #11.#41        // ClassTest.variable:I
   #7 = Fieldref           #11.#42        // ClassTest.variable2:Ljava/lang/String;
   #8 = Fieldref           #11.#43        // ClassTest.variableInt:I
   #9 = String             #44            // 我很好
  #10 = Fieldref           #11.#45        // ClassTest.variableString:Ljava/lang/String;
  #11 = Class              #46            // ClassTest
  #12 = Class              #47            // java/lang/Object
  #13 = Utf8               constantInt
  #14 = Utf8               I
  #15 = Utf8               ConstantValue
  #16 = Integer            12
  #17 = Utf8               constantString
  #18 = Utf8               Ljava/lang/String;
  #19 = Utf8               variableInt
  #20 = Utf8               variableString
  #21 = Utf8               variable
  #22 = Utf8               variable2
  #23 = Utf8               main
  #24 = Utf8               ([Ljava/lang/String;)V
  #25 = Utf8               Code
  #26 = Utf8               LineNumberTable
  #27 = Utf8               say
  #28 = Utf8               ()V
  #29 = Utf8               <init>
  #30 = Utf8               (ILjava/lang/String;)V
  #31 = Utf8               <clinit>
  #32 = Utf8               SourceFile
  #33 = Utf8               ClassTest.java
  #34 = Class              #48            // java/lang/System
  #35 = NameAndType        #49:#50        // out:Ljava/io/PrintStream;
  #36 = Utf8               --这是main()方法---
  #37 = Class              #51            // java/io/PrintStream
  #38 = NameAndType        #52:#53        // println:(Ljava/lang/String;)V
  #39 = Utf8               这是普通方法
  #40 = NameAndType        #29:#28        // "<init>":()V
  #41 = NameAndType        #21:#14        // variable:I
  #42 = NameAndType        #22:#18        // variable2:Ljava/lang/String;
  #43 = NameAndType        #19:#14        // variableInt:I
  #44 = Utf8               我很好
  #45 = NameAndType        #20:#18        // variableString:Ljava/lang/String;
  #46 = Utf8               ClassTest
  #47 = Utf8               java/lang/Object
  #48 = Utf8               java/lang/System
  #49 = Utf8               out
  #50 = Utf8               Ljava/io/PrintStream;
  #51 = Utf8               java/io/PrintStream
  #52 = Utf8               println
  #53 = Utf8               (Ljava/lang/String;)V
{
  static final int constantInt;
    descriptor: I
    flags: ACC_STATIC, ACC_FINAL
    ConstantValue: int 12

  static final java.lang.String constantString;
    descriptor: Ljava/lang/String;
    flags: ACC_STATIC, ACC_FINAL
    ConstantValue: String 我很好

  static int variableInt;
    descriptor: I
    flags: ACC_STATIC

  static java.lang.String variableString;
    descriptor: Ljava/lang/String;
    flags: ACC_STATIC

  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     #1                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #2                  // String --这是main()方法---
         5: invokevirtual #3                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 11: 0
        line 13: 8

  public void say();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #1                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #4                  // String 这是普通方法
         5: invokevirtual #3                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 15: 0
        line 16: 8

  public ClassTest(int, java.lang.String);
    descriptor: (ILjava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=3
         0: aload_0
         1: invokespecial #5                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iload_1
         6: putfield      #6                  // Field variable:I
         9: aload_0
        10: aload_2
        11: putfield      #7                  // Field variable2:Ljava/lang/String;
        14: return
      LineNumberTable:
        line 18: 0
        line 19: 4
        line 20: 9
        line 21: 14

  public ClassTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #5                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 22: 0
        line 24: 4

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: bipush        12
         2: putstatic     #8                  // Field variableInt:I
         5: ldc           #9                  // String 我很好
         7: putstatic     #10                 // Field variableString:Ljava/lang/String;
        10: return
      LineNumberTable:
        line 5: 0
        line 6: 5
}
SourceFile: "ClassTest.java"
View Code

简单版本:

  

 minor version: 0        //---主版本号
  major version: 52        //---次版本号      
  flags: ACC_PUBLIC, ACC_SUPER    //---类访问标识
 //--- 常量池 
Constant pool:
   #1 = Fieldref           #34.#35        // java/lang/System.out:Ljava/io/PrintStream;
   #2 = String             #36            // --这是main()方法---
   .......
   #52 = Utf8               println
   #53 = Utf8               (Ljava/lang/String;)V
{
//--- 字段信息
  static final int constantInt;
    descriptor: I
    flags: ACC_STATIC, ACC_FINAL
    ConstantValue: int 12


  static int variableInt;
    descriptor: I
    flags: ACC_STATIC


//---方法信息
  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     #1                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #2                  // String --这是main()方法---
         5: invokevirtual #3                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 11: 0
        line 13: 8

 
  public ClassTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #5                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 22: 0
        line 24: 4
        
//-- super()方法
  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: bipush        12
         2: putstatic     #8                  // Field variableInt:I
         5: ldc           #9                  // String 我很好
         7: putstatic     #10                 // Field variableString:Ljava/lang/String;
        10: return
      LineNumberTable:
        line 5: 0
        line 6: 5
}

 class 文件内容项

  

 magic(魔数) : class文件前四位字节,class文件总是以 0xCAFEBABE 开头,作为class文件标识。

minor_version / major_version  主次版本号,JVM 根据版本号决定如何加载class文件

constant_pool_count / constant_pool :常量池

  每一个常量池入口都是从一个标识(长度是一个字节)开始。次标识指明该位置常量的类型。

  每一个标志都有一个相对的表,表名就是标志名加上“_info”  即 constant_utf8_info

  

  常量池具体描述 : https://blog.csdn.net/hxcaifly/article/details/82887552

access_flage : 访问标志,指明class文件定义的是类还是接口,以及类或接口的修饰符。

  

this_class :就是指向常量池中constant_class_info的索引。

super_class :也是一个指向常量池的索引。

interfaces / fields / methods /attribute  :也是指向常量池的索引。

XXX_count :就是对应的数量。

 

posted @ 2019-07-24 16:04  窦婴  阅读(292)  评论(0编辑  收藏  举报