专业的JAVA编程教程与资源

网站首页 > java教程 正文

【JVM字节码】Class文件与字节码,机器码的关系

temp10 2025-01-07 15:58:19 java教程 12 ℃ 0 评论

class字节码


class文件(二进制)和字节码(十六进制)的关系

  • class文件是经过编译器编译后的文件(如javac),一个class文件代表一个类或者接口;class文件主要存储的是字节码,字节码是访问jvm的重要指令,在后面的章节中会介绍字节码的相关信息。jvm规范定义了class文件结构格式,每种jvm实现必须满足规范定义,这样jvm实例才能加载class文件,运行字节码内容。但jvm的实现可以在jvm规范的约束下对具体实现做出修改和优化(如自定义属性信息,jvm会忽略不认识的属性表)。class文件的内容(.class文件本身是2进制)一般是16进制的数。 JVM加载的Class文件不一定来自磁盘,还可以来自网络数据,甚至在运行时直接编译代码字符串生成。 ---------节选《深入了解虚拟机》
  • 机器码我理解是CPU的指令集。字节码是由opcode(操作码)和操作数组成的。class文件并不叫字节码,class文件是由字节码组成的。字节码你可以理解为是JVM的指令。JVM是一个运行在CPU上的程序,JVM本身是由一条条机器码组成的,它的功能是读取一条条字节码,并在CPU上执行。
  • 也就是说是将二进制的文件加载JVM时,JVM将使用十六进制的方式读取class文件中的字节码(编译期间就确定好了

.java和.class的区别

  1. java文件是源文件,通过javac命令编译后生成.class文件;.class文件是字节码结文件,即.java文件编译后的代码。
  2. class文件全名称为Java class文件,主要在平台无关性和网络移动性方面使Java更适合网络。
  3. 通俗来说java文件就是这样一个未经编译的源程序,一般是给程序员看的。class文件就是被编译器编译过的java文件,通常是给计算机看的。
  4. 也就是说.java是我们开发语言.class生成的16进制字节码是方便机器看的因为java源文件存在太多换行导致内存占用过多(机器不会识别空格)
  5. jvm规范和Java规范是不同的不能拿java的思维去套用jvm

示例

public class MyTest1 {

    private int a = 1;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
}


执行

【JVM字节码】Class文件与字节码,机器码的关系


javac MyTest1.java
//打印公有信息
javap -verbose MyTest1.class
//将私有的方法信息也打印出来
javap -verbose -p MyTest1.class

得到对应字节码


  Last modified 2020-9-13; size 375 bytes
  MD5 checksum 8ba81fc79a80d987e02b14067a155703
  Compiled from "MyTest1.java"
public class com.example.demo.com.jvm.bytecode.MyTest1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#18         //com/example/demo/com/jvm/bytecode/MyTest1.a:I
   #3 = Class              #19            // com/example/demo/com/jvm/bytecode/MyTest1
   #4 = Class              #20            // java/lang/Object
   #5 = Utf8               a
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               getA
  #12 = Utf8               ()I
  #13 = Utf8               setA
  #14 = Utf8               (I)V
  #15 = Utf8               SourceFile
  #16 = Utf8               MyTest1.java
  #17 = NameAndType        #7:#8          // "<init>":()V
  #18 = NameAndType        #5:#6          // a:I
  #19 = Utf8               com/example/demo/com/jvm/bytecode/MyTest1
  #20 = Utf8               java/lang/Object
{
  public com.example.demo.com.jvm.bytecode.MyTest1();
    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: iconst_1
         6: putfield      #2                  // Field a:I
         9: return
      LineNumberTable:
        line 3: 0
        line 5: 4

  public int getA();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field a:I
         4: ireturn
      LineNumberTable:
        line 8: 0

  public void setA(int);
    descriptor: (I)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: iload_1
         2: putfield      #2                  // Field a:I
         5: return
      LineNumberTable:
        line 12: 0
        line 13: 5
}
SourceFile: "MyTest1.java"

字节码整体结构


class文件只有两种数据类型:无符号数和表

这里面表就类似常量池 是一种数据结构的复合形式

方法区包含如下内容




Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表