详解 JVM 字节码(2)

匿名 (未验证) 提交于 2019-12-02 23:32:01

jvm

什么是字节码,为什么需要字节码
编译 JVM 编译成机器码,

我们看一看 Java 编译过程

  • java 源码
  • 编译为 class 文件

JVM 接收字节码文件后对其进行校验
验证字节码文件正确性然后通过类加载器加载生成 class 类来运行
【图】

为什么学习字节码?

大家都知道 java 文件编译后为二进制的字节码文件可以被 JVM 读懂,学习好字节码文件可以让我们对 Java 这门语言有深入了解。只要遵循 JVM 规范你就可以创建出自己语言。可以反编译一些第三方库。

java 规范分为两种

  • java 语言本身的规范
  • JVM 的规范。字节码属于 JVM 规范。JVM 只是关心字节码

这里我们整个字节码分析都会以整个类文件,通过读整个类编译后的字节码来学习字节码。

 package com.zidea;  public class Tut {     private String title = "basic";     private int courses = 10;      public String getTitle() {         return title;     }      public void setTitle(String title) {         this.title = title;     }      public int getCourses() {         return courses;     }      public void setCourses(int courses) {         this.courses = courses;     } }  

使用 javap 命令查看编译好的 Tut.class 文件

 javap Tut.class  
 public class com.zidea.Tut {   public com.zidea.Tut();   public java.lang.String getTitle();   public void setTitle(java.lang.String);   public int getCourses();   public void setCourses(int); }  
  javap -c Tut.class 

用命令查看 class 文件我们可以查看到许多助记符

 javap -verbose Tut.class  
 jangwoodeMacBook-Air:zidea jangwoo$ javap -c Tut.class Compiled from "Tut.java" public class com.zidea.Tut {   public com.zidea.Tut();     Code:        0: aload_0        1: invokespecial #1                  // Method java/lang/Object."<init>":()V        4: aload_0        5: ldc           #2                  // String basic        7: putfield      #3                  // Field title:Ljava/lang/String;       10: aload_0       11: bipush        10       13: putfield      #4                  // Field courses:I       16: return    public java.lang.String getTitle();     Code:        0: aload_0        1: getfield      #3                  // Field title:Ljava/lang/String;        4: areturn    public void setTitle(java.lang.String);     Code:        0: aload_0        1: aload_1        2: putfield      #3                  // Field title:Ljava/lang/String;        5: return    public int getCourses();     Code:        0: aload_0        1: getfield      #4                  // Field courses:I        4: ireturn    public void setCourses(int);     Code:        0: aload_0        1: iload_1        2: putfield      #4                  // Field courses:I        5: return }  

javap -verbose 命令来分析字节码文件

  • 魔数
  • 版本号
  • 常量池
  • 类信息 ,class 信息不会丢失在进入 JVM
  • 类的构造方法
  • 类中的方法信息
  • 类变量与成员变量等信息
 Classfile /Users/jangwoo/IdeaProjects/jvm_demo/out/production/jvm_demo/com/zidea/Tut.class   Last modified May 2, 2019; size 746 bytes   MD5 checksum e58553db6eb469ec2411f8711ace986a   Compiled from "Tut.java" public class com.zidea.Tut   minor version: 0   major version: 54   flags: (0x0021) ACC_PUBLIC, ACC_SUPER   this_class: #5                          // com/zidea/Tut   super_class: #6                         // java/lang/Object   interfaces: 0, fields: 2, methods: 5, attributes: 1 Constant pool:    #1 = Methodref          #6.#28         // java/lang/Object."<init>":()V    #2 = String             #29            // basic    #3 = Fieldref           #5.#30         // com/zidea/Tut.title:Ljava/lang/String;    #4 = Fieldref           #5.#31         // com/zidea/Tut.courses:I    #5 = Class              #32            // com/zidea/Tut    #6 = Class              #33            // java/lang/Object    #7 = Utf8               title    #8 = Utf8               Ljava/lang/String;    #9 = Utf8               courses   #10 = Utf8               I   #11 = Utf8               <init>   #12 = Utf8               ()V   #13 = Utf8               Code   #14 = Utf8               LineNumberTable   #15 = Utf8               LocalVariableTable   #16 = Utf8               this   #17 = Utf8               Lcom/zidea/Tut;   #18 = Utf8               getTitle   #19 = Utf8               ()Ljava/lang/String;   #20 = Utf8               setTitle   #21 = Utf8               (Ljava/lang/String;)V   #22 = Utf8               getCourses   #23 = Utf8               ()I   #24 = Utf8               setCourses   #25 = Utf8               (I)V   #26 = Utf8               SourceFile   #27 = Utf8               Tut.java   #28 = NameAndType        #11:#12        // "<init>":()V   #29 = Utf8               basic   #30 = NameAndType        #7:#8          // title:Ljava/lang/String;   #31 = NameAndType        #9:#10         // courses:I   #32 = Utf8               com/zidea/Tut   #33 = Utf8               java/lang/Object {   public com.zidea.Tut();     descriptor: ()V     flags: (0x0001) 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 basic          7: putfield      #3                  // Field title:Ljava/lang/String;         10: aload_0         11: bipush        10         13: putfield      #4                  // Field courses:I         16: return       LineNumberTable:         line 3: 0         line 4: 4         line 5: 10       LocalVariableTable:         Start  Length  Slot  Name   Signature             0      17     0  this   Lcom/zidea/Tut;    public java.lang.String getTitle();     descriptor: ()Ljava/lang/String;     flags: (0x0001) ACC_PUBLIC     Code:       stack=1, locals=1, args_size=1          0: aload_0          1: getfield      #3                  // Field title:Ljava/lang/String;          4: areturn       LineNumberTable:         line 8: 0       LocalVariableTable:         Start  Length  Slot  Name   Signature             0       5     0  this   Lcom/zidea/Tut;    public void setTitle(java.lang.String);     descriptor: (Ljava/lang/String;)V     flags: (0x0001) ACC_PUBLIC     Code:       stack=2, locals=2, args_size=2          0: aload_0          1: aload_1          2: putfield      #3                  // Field title:Ljava/lang/String;          5: return       LineNumberTable:         line 12: 0         line 13: 5       LocalVariableTable:         Start  Length  Slot  Name   Signature             0       6     0  this   Lcom/zidea/Tut;             0       6     1 title   Ljava/lang/String;    public int getCourses();     descriptor: ()I     flags: (0x0001) ACC_PUBLIC     Code:       stack=1, locals=1, args_size=1          0: aload_0          1: getfield      #4                  // Field courses:I          4: ireturn       LineNumberTable:         line 16: 0       LocalVariableTable:         Start  Length  Slot  Name   Signature             0       5     0  this   Lcom/zidea/Tut;    public void setCourses(int);     descriptor: (I)V     flags: (0x0001) ACC_PUBLIC     Code:       stack=2, locals=2, args_size=2          0: aload_0          1: iload_1          2: putfield      #4                  // Field courses:I          5: return       LineNumberTable:         line 20: 0         line 21: 5       LocalVariableTable:         Start  Length  Slot  Name   Signature             0       6     0  this   Lcom/zidea/Tut;             0       6     1 courses   I } SourceFile: "Tut.java" 

这里我们按顺序了解一下 java 字节码是由哪些部分组成,然后对照创建 Tut的字节码文件进行分析

字节码整体结构


这张表中是按顺序指出我们字节码中内容。

java 字节码中有两种数据类型

  • 字节数据直接量:为基本的数据类型,例如 u1、u2、u4 和 u8,分别代表连续的 1 字节、2 字节、4字节和 8 字节组成整体数据。
  • 表(数组):表是由多个基本数据或其他表,按照既定顺序组成的数据集合。例如常量池就是表。
    其中表长度是不固定的,他是元素类型(不同类型有不同内容)和元素数量决定。

魔数

所有 class 字节码文件的前 4 个字节都是魔数,魔数值为固定值CA FE BA BE

屏幕快照 2019-05-02 下午8.36.59.png

单个字节,CA 表示一个字节,C 是 16 进制由 4 位来表示16进制,CA 两个在一起表示 8 位。JVM 编译出来的字节码文件是以 8 位字节为最小单位构成。

如果有想学习java的程序员,可来我们的java学习扣qun:697699179,免费送java的视频教程噢!我每晚上8点还会在群内直播讲解Java知识,欢迎大家前来学习哦。

文章来源: https://blog.csdn.net/sdssdfh/article/details/89790776
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!