JVM 字节码文件

计算机不能直接运行java代码,要先运行虚拟机,再由java虚拟机运行编译后java代码。

为什么不能直接运行java代码?

计算机所有的操作都是通过一个个指令集汇集后去完成的。java 是高级语言,只有人才能理解它的逻辑,机器是无法识别。所以需要将java文件编译成JVM能后识别的字节码文件,这样JVM才能正确的识别代码转换后的指令去正确的执行它。

  • java代码转换成字节码文件后,在交由部署到不同平台JVM去读取执行。从而实现了一次编译,到处运行。
  • JVM 不只是支持java,衍生了很多基于JVM的语言,如Groovy、Scala、Koltin、JRuby、Jython等

Java字节码文件

class文件本质上是一个以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在class文件中。jvm根据其特定的规则解析该二进制数据,从而得到相关信息。

class文件结构属性

在这里插入图片描述

  • 魔数:每一个.class文件的前四个字节成为魔数,值为0xCAFEBABE (咖啡宝贝?) 用来确定文件是一个.class文件,很多类型的文件都是有魔数的,只靠文件名是不能确定文件类型的,所以每种文件都有对应的魔数来标识它,比如: jpg、png 等

  • 次版本和主版本:用来表示编一个class文件使用的jdk版本,次版本一版为0,如果主版本号为0034转化为十进制是52,在jdk 1.0和1.1 使用了45,以后每一个大版本在上一个版本的基础上加一。可以看看出jdk是 1.8.0

  • 常量池: 用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)

  • 访问标记:用于表示该class的访问类型和属性,比如访问类型是不是pulic,能不能被标记为final

  • 父类索引、类索引、接口索引:通过这三种索引来描述类的继承关系

  • 字段表属性:用于描述接口或类中声明的变量,比如:变量的作用域、是不是静态变量、 数据类型

  • 方法表属性:和字段表属性类似,只不过用于描述方法的类型和作用域

  • 属性表属性:用于描述特定场景的信息,比如:字段表属性的特殊属性等

生成一个class文件
javac UserDTO.java

使用javac 命令会在同一路径下生成一个跟文件同名的.class文件

反编译.class文件
javap -v UserDTO.class
$ javap -v UserDTO.class
Classfile /C:/Users/zhaotianxin/Desktop/hzero_c7n/redis/src/main/java/icu/fastwo
rm/redis/UserDTO.class
  Last modified 2021-8-4; size 831 bytes
  MD5 checksum 48a05888aaba92b73e52e159bb7fd612
  Compiled from "UserDTO.java"
public class icu.fastworm.redis.UserDTO implements java.io.Serializable
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#29         // java/lang/Object."<init>":()V
   #2 = Fieldref           #5.#30         // icu/fastworm/redis/UserDTO.name:Lja
va/lang/String;
   #3 = Fieldref           #5.#31         // icu/fastworm/redis/UserDTO.word:Lja
va/lang/String;
   #4 = Fieldref           #5.#32         // icu/fastworm/redis/UserDTO.id:Ljava
/lang/Long;
   #5 = Class              #33            // icu/fastworm/redis/UserDTO
   #6 = Class              #34            // java/lang/Object
   #7 = Class              #35            // java/io/Serializable
   #8 = Utf8               id
   #9 = Utf8               Ljava/lang/Long;
  #10 = Utf8               name
  #11 = Utf8               Ljava/lang/String;
  #12 = Utf8               word
  #13 = Utf8               <init>
  #14 = Utf8               (Ljava/lang/String;Ljava/lang/String;)V
  #15 = Utf8               Code
  #16 = Utf8               LineNumberTable
  #17 = Utf8               getId
  #18 = Utf8               ()Ljava/lang/Long;
  #19 = Utf8               setId
  #20 = Utf8               (Ljava/lang/Long;)V
  #21 = Utf8               getName
  #22 = Utf8               ()Ljava/lang/String;
  #23 = Utf8               setName
  #24 = Utf8               (Ljava/lang/String;)V
  #25 = Utf8               getWord
  #26 = Utf8               setWord
  #27 = Utf8               SourceFile
  #28 = Utf8               UserDTO.java
  #29 = NameAndType        #13:#36        // "<init>":()V
  #30 = NameAndType        #10:#11        // name:Ljava/lang/String;
  #31 = NameAndType        #12:#11        // word:Ljava/lang/String;
  #32 = NameAndType        #8:#9          // id:Ljava/lang/Long;
  #33 = Utf8               icu/fastworm/redis/UserDTO
  #34 = Utf8               java/lang/Object
  #35 = Utf8               java/io/Serializable
  #36 = Utf8               ()V
{
  public icu.fastworm.redis.UserDTO(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=3
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>
":()V
         4: aload_0
         5: aload_1
         6: putfield      #2                  // Field name:Ljava/lang/String;
         9: aload_0
        10: aload_2
        11: putfield      #3                  // Field word:Ljava/lang/String;
        14: return
      LineNumberTable:
        line 16: 0
        line 17: 4
        line 18: 9
        line 19: 14

  public java.lang.Long getId();
    descriptor: ()Ljava/lang/Long;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #4                  // Field id:Ljava/lang/Long;
         4: areturn
      LineNumberTable:
        line 22: 0

  public void setId(java.lang.Long);
    descriptor: (Ljava/lang/Long;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #4                  // Field id:Ljava/lang/Long;
         5: return
      LineNumberTable:
        line 26: 0
        line 27: 5

  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      #2                  // Field name:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 30: 0

  public void setName(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #2                  // Field name:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 34: 0
        line 35: 5

  public java.lang.String getWord();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #3                  // Field word:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 38: 0

  public void setWord(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #3                  // Field word:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 42: 0
        line 43: 5
}
SourceFile: "UserDTO.java"

常量池

字面量

字面量类似于java中的常量概念,如文本字符串,final常量等

符号引用
  • 类和接口的全限定名(Fully Qualified Name)
  • 字段的名称和描述符号(Descriptor)
  • 方法的名称和描述符
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值