IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java字节码文件结构 -> 正文阅读

[Java知识库]Java字节码文件结构

Java字节码文件结构

查看字节码的方法

  • 使用javap命令。如javap -v Person.class输出字节码信息,javap -v -p Person.class输出完整字节码信息。
  • 使用jclasslib插件。

字节码文件标识说明

类访问标记

标记名说明
ACC_PUBLIC是否为public
ACC_FINAL是否为final
ACC_SUPER兼容旧版本,Java1.1及以上版本始终设置该值
ACC_INTERFACE是否为接口
ACC_ABSTRACT是否为抽象,接口和抽象类有此标记
ACC_SYNTHETIC这个类的代码不是用户代码
ACC_ANNOTATION是否为注解
ACC_ENUM是否为枚举

字段类型标识符

标识字符说明
B原始数据类型byte
C原始数据类型char
D原始数据类型double
F原始数据类型float
I原始数据类型int
J原始数据类型long
S原始数据类型short
Z原始数据类型boolean
V特殊类型void
L引用数据类型,以分号“;”结尾
[一维数组

字段标识符

字段的标识符与类的非常类似。

标识符说明
ACC_PUBLIC是否为public
ACC_PRIVATE是否为private
ACC_PROTECTED是否为protected
ACC_STATIC是否为static
ACC_FINAL是否为final
ACC_VOLATILE是否为volatile
ACC_TRANSIENT是否序列化
ACC_SYNTHETIC是否由编译器自动生成
ACC_ENUM是否为枚举

方法标识符

标识符说明
ACC_PUBLIC是否为public
ACC_PRIVATE是否为private
ACC_PROTECTED是否为protected
ACC_STATIC是否为static
ACC_FINAL是否为final
ACC_SYNCHRONIZED是否为synchronized
ACC_NATIVE是否为本地方法
ACC_SYNTHETIC是否由编译器自动生成
ACC_ABSTRACT是否为抽象方法
ACC_STRICT限制浮点计算以确保可移植性
ACC_VARARGS是否能接收可变参数

字节码文件结构说明

编译生产字节码

public class Person {
    private String name = "小明";
    private int age = 18;
    private final int NO = 10068;

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

在这里插入图片描述

说明:将Person类进行编译,生成Person.class文件,打开文件可以看到里面的内容。

  • 开头是CAFE BABE,这4个字节称为默数,是字节码文件的身份标识,只有以CA FE BA BE开头的class文件才能被JVM接受。
  • 再往后是00 00表示Java的次版本号,00 34表示主版本号。
  • 再往后就是字符串常量池。

反编译字节码文件

Java内置javap命令可以反编译查看字节码文件,或者通过jclasslib插件也可以查看。

通过javap -v Person.class命令查看输出信息:

Classfile /D:/TestWorkspace/AndroidDemo/lib_java/build/classes/java/main/com/example/lib_java/Person.class
  Last modified 2022-3-3; size 624 bytes
  MD5 checksum 44c9bd227e49c0b8440e0f10143b753d
  Compiled from "Person.java"
public class com.example.lib_java.Person
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #7.#28         // java/lang/Object."<init>":()V
   #2 = String             #29            // 小明
   #3 = Fieldref           #6.#30         // com/example/lib_java/Person.name:Ljava/lang/String;
   #4 = Fieldref           #6.#31         // com/example/lib_java/Person.age:I
   #5 = Fieldref           #6.#32         // com/example/lib_java/Person.NO:I
   #6 = Class              #33            // com/example/lib_java/Person
   #7 = Class              #34            // java/lang/Object
   #8 = Utf8               name
   #9 = Utf8               Ljava/lang/String;
  #10 = Utf8               age
  #11 = Utf8               I
  #12 = Utf8               NO
  #13 = Utf8               ConstantValue
  #14 = Integer            10068
  #15 = Utf8               <init>
  #16 = Utf8               ()V
  #17 = Utf8               Code
  #18 = Utf8               LineNumberTable
  #19 = Utf8               LocalVariableTable
  #20 = Utf8               this
  #21 = Utf8               Lcom/example/lib_java/Person;
  #22 = Utf8               getName
  #23 = Utf8               ()Ljava/lang/String;
  #24 = Utf8               getAge
  #25 = Utf8               ()I
  #26 = Utf8               SourceFile
  #27 = Utf8               Person.java
  #28 = NameAndType        #15:#16        // "<init>":()V
  #29 = Utf8               小明
  #30 = NameAndType        #8:#9          // name:Ljava/lang/String;
  #31 = NameAndType        #10:#11        // age:I
  #32 = NameAndType        #12:#11        // NO:I
  #33 = Utf8               com/example/lib_java/Person
  #34 = Utf8               java/lang/Object
{
  private java.lang.String name;
    descriptor: Ljava/lang/String;
    flags: ACC_PRIVATE

  private int age;
    descriptor: I
    flags: ACC_PRIVATE

  private final int NO;
    descriptor: I
    flags: ACC_PRIVATE, ACC_FINAL
    ConstantValue: int 10068

  public com.example.lib_java.Person();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String 小明
         7: putfield      #3                  // Field name:Ljava/lang/String;
        10: aload_0
        11: bipush        18
        13: putfield      #4                  // Field age:I
        16: aload_0
        17: sipush        10068
        20: putfield      #5                  // Field NO:I
        23: return
      LineNumberTable:
        line 3: 0
        line 4: 4
        line 5: 10
        line 6: 16
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      24     0  this   Lcom/example/lib_java/Person;

  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      #3                  // Field name:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 9: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/example/lib_java/Person;

  public int getAge();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #4                  // Field age:I
         4: ireturn
      LineNumberTable:
        line 13: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/example/lib_java/Person;
}
SourceFile: "Person.java"

第1部分:字节码的描述

Classfile /D:/*/*/*/build/classes/java/main/com/example/lib_java/Person.class
  Last modified 2022-3-3; size 560 bytes
  MD5 checksum ed1b841f2fb00defe07401da1d8c129f
  Compiled from "Person.java"

依次说明:

  1. 字节码文件的存放位置。
  2. 字节码文件修改日期和文件大小。
  3. 生成唯一值MD5。
  4. 生成字节码文件的源文件是Person.java

第2部分:类的描述

public class com.example.lib_java.Person
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER

依次说明:

  1. 字节码文件的类全名。
  2. 次版本号。
  3. 主版本号。
  4. 类访问标记,一共8种。

第3部分:常量池

第3部分是常量池,是字节码文件的重要部分,主要存放两类信息:

  • 字面量:字符串、final常量等;
  • 符合引用:类和接口的全限定名、字段的名称和描述符、方法的名称和描述符。

注:

  • #号后面是索引,索引从1开始,索引没有从0开始,是因为设计者考虑到不引用任何常量时,可以将索引设置为0来表示。
  • =号后面是常量的类型。
Constant pool:
   #1 = Methodref          #7.#28         // java/lang/Object."<init>":()V
   #2 = String             #29            // 小明
   #3 = Fieldref           #6.#30         // com/example/lib_java/Person.name:Ljava/lang/String;
   #4 = Fieldref           #6.#31         // com/example/lib_java/Person.age:I
   #5 = Fieldref           #6.#32         // com/example/lib_java/Person.NO:I
   #6 = Class              #33            // com/example/lib_java/Person
   #7 = Class              #34            // java/lang/Object
   #8 = Utf8               name
   #9 = Utf8               Ljava/lang/String;
  #10 = Utf8               age
  #11 = Utf8               I
  #12 = Utf8               NO
  #13 = Utf8               ConstantValue
  #14 = Integer            10068
  #15 = Utf8               <init>
  #16 = Utf8               ()V
  #17 = Utf8               Code
  #18 = Utf8               LineNumberTable
  #19 = Utf8               LocalVariableTable
  #20 = Utf8               this
  #21 = Utf8               Lcom/example/lib_java/Person;
  #22 = Utf8               getName
  #23 = Utf8               ()Ljava/lang/String;
  #24 = Utf8               getAge
  #25 = Utf8               ()I
  #26 = Utf8               SourceFile
  #27 = Utf8               Person.java
  #28 = NameAndType        #15:#16        // "<init>":()V
  #29 = Utf8               小明
  #30 = NameAndType        #8:#9          // name:Ljava/lang/String;
  #31 = NameAndType        #10:#11        // age:I
  #32 = NameAndType        #12:#11        // NO:I
  #33 = Utf8               com/example/lib_java/Person
  #34 = Utf8               java/lang/Object

依次说明:

  1. #1常量的类型是Methodref,表示用来定义方法的,#1常量指向常量池中#7和#28的常量。
  2. #7常量类型是Class,表示用来定义类或接口,指向#34常量。
  3. #34常量类型是Utf8的字符串,值为java/lang/Object
  4. #28常量类型是NameAndType,表示字段或方法的部分符号引用,指向常量池中的#15和#16常量。
  5. #15常量类型是Utf8的字符串,值为<init>,表示为构造方法。
  6. #16常量类型是Utf8的字符串,值为()V,表示方法的返回值是void。

总结#1常量,Person类的使用默认的构造方法,来源自Object类。

  1. #2常量的类型是String,指向#29常量。
  2. #29常量的类型是Utf8的字符串,值为小明。

总结#2常量,定义类一个为“小明”的字符串。

  1. #3常量的类型是Fieldref,表示用来定义字段的,指向#6和#30常量。
  2. #6常量的类型是Class,指向#33常量。
  3. #33常量的类型是Utf8的字符串,值是com/example/lib_java/Person
  4. #30常量的类型是NameAndType,指向 #8和#9常量。
  5. #8常量的类型是Utf8的字符串,值是name
  6. #9常量的类型是Utf8的字符串,值是Ljava/lang/String

总结#3常量,声明了一个类型为String的字段name。

第4部分:字段表

字段表是用于描述类或接口中声明的字段,包含类变量和成员变量,不包含局部变量。

  private java.lang.String name;
    descriptor: Ljava/lang/String;
    flags: ACC_PRIVATE

依次说明:

  1. 表示该字段的访问修饰符是private,类型是String,字段名是name

第5部分:方法表

方法表用于描述类或接口中声明的方法。

  public com.example.lib_java.Person();
    descriptor: ()V
    flags: ACC_PUBLIC

依次说明:

  1. 表示该方法是构造方法,返回值类型是void,访问修饰符是public
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String 小明
         7: putfield      #3                  // Field name:Ljava/lang/String;
        10: aload_0
        11: bipush        18
        13: putfield      #4                  // Field age:I
        16: aload_0
        17: sipush        10068
        20: putfield      #5                  // Field NO:I
        23: return
      LineNumberTable:
        line 3: 0
        line 4: 4
        line 5: 10
        line 6: 16
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      24     0  this   Lcom/example/lib_java/Person;

依次说明:

  1. stack:最大操作数占,JVM在运行时会根据这个值分配栈帧。为什么是2,因为会调用父类的构造方法。
  2. locals:局部变量数量。隐藏了this变量。
  3. args_size:形参数量。默认传入this变量。
  4. LineNumberTable:描述源码行号与字节码行号之间的对应关系。
  5. LocalVariableTable:描述栈帧中的局部变量与源码中定义的变量之间的关系,其中的this。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:22:29  更:2022-03-04 15:23:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:44:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码