前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Java 虚拟机原理】Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 )

【Java 虚拟机原理】Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 )

作者头像
韩曙亮
发布2023-03-29 16:28:21
4230
发布2023-03-29 16:28:21
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、字节码文件 与 JVM


Java 源码编译成 Class 字节码 ;

Java 虚拟机 可以被认为是一个 解释器 , 解释编译后的 Class 字节码文件 , 最后在不同的操作系统中运行 ;

Android 虚拟机 不是 Java 规范的 虚拟机 , 有一些根据嵌入式设备进行的定制的实现 ;

Class 字节码 本质上就是 二进制数据 , 运行时 , 会被 类加载器 加载到 Java 虚拟机内存的 方法区 中 ; 同时 创建 Class 对象 ; ( Java 虚拟机内存分为 : 堆区 , 方法区 , 栈 , 本地方法栈 , 程序计数器 )

由于要将 Class 字节码文件 加载到 JVM 内存的 方法区 中 , 要占用一定的内存空间 , 这里要求 Class 字节码文件 , 越小越好 ;

二、字节码文件示例


Java 源代码如下 :

代码语言:javascript
复制
public class Student {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

使用 javac 命令将 Student.java 源码编译成 Student.class字节码文件 :

代码语言:javascript
复制
javac Student.java

字节码文件二进制数据分析 :

使用二进制查看工具查看 Student.class 字节码文件 , 这些二进制数值对应的就是 JVM 指令 ;

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
CA FE BA BE 00 00 00 34 00 15 0A 00 04 00 11 09 
00 03 00 12 07 00 13 07 00 14 01 00 04 6E 61 6D 
65 01 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 
74 72 69 6E 67 3B 01 00 06 3C 69 6E 69 74 3E 01 
00 03 28 29 56 01 00 04 43 6F 64 65 01 00 0F 4C 
69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 01 00 
07 67 65 74 4E 61 6D 65 01 00 14 28 29 4C 6A 61 
76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 01 
00 07 73 65 74 4E 61 6D 65 01 00 15 28 4C 6A 61 
76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 
56 01 00 0A 53 6F 75 72 63 65 46 69 6C 65 01 00 
0C 53 74 75 64 65 6E 74 2E 6A 61 76 61 0C 00 07 
00 08 0C 00 05 00 06 01 00 07 53 74 75 64 65 6E 
74 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 
6A 65 63 74 00 21 00 03 00 04 00 00 00 01 00 02 
00 05 00 06 00 00 00 03 00 01 00 07 00 08 00 01 
00 09 00 00 00 1D 00 01 00 01 00 00 00 05 2A B7 
00 01 B1 00 00 00 01 00 0A 00 00 00 06 00 01 00 
00 00 01 00 01 00 0B 00 0C 00 01 00 09 00 00 00 
1D 00 01 00 01 00 00 00 05 2A B4 00 02 B0 00 00 
00 01 00 0A 00 00 00 06 00 01 00 00 00 05 00 01 
00 0D 00 0E 00 01 00 09 00 00 00 22 00 02 00 02 
00 00 00 06 2A 2B B5 00 02 B1 00 00 00 01 00 0A 
00 00 00 0A 00 02 00 00 00 09 00 05 00 0A 00 01 
00 0F 00 00 00 02 00 10

使用

代码语言:javascript
复制
javap -v Student.class

命令 , 生成上述字节码文件的 附加信息 ;

命令行输出 :

代码语言:javascript
复制
D:\jvm>javap -v Student.class
Classfile /D:/jvm/Student.class
  Last modified 2021-9-4; size 392 bytes
  MD5 checksum 8b9bb897bb8cf2a8addf04be5b7b915f
  Compiled from "Student.java"
public class Student
  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         // Student.name:Ljava/lang/String;
   #3 = Class              #19            // Student
   #4 = Class              #20            // java/lang/Object
   #5 = Utf8               name
   #6 = Utf8               Ljava/lang/String;
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               getName
  #12 = Utf8               ()Ljava/lang/String;
  #13 = Utf8               setName
  #14 = Utf8               (Ljava/lang/String;)V
  #15 = Utf8               SourceFile
  #16 = Utf8               Student.java
  #17 = NameAndType        #7:#8          // "<init>":()V
  #18 = NameAndType        #5:#6          // name:Ljava/lang/String;
  #19 = Utf8               Student
  #20 = Utf8               java/lang/Object
{
  public Student();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  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 5: 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 9: 0
        line 10: 5
}
SourceFile: "Student.java"
在这里插入图片描述
在这里插入图片描述

下面开始逐个字节解析上述字节码文件 ;

三、字节码文件二进制结构分析


分析字节码二进制文件时 , 可以参考 javap -v Student.class 命令输出的字节码附加信息进行理解 ;

1、魔数

magic ( 魔数 ) :

4

字节 , CA FE BA BE , 所有的 Class 字节码都是以 CafeBabe 信息开头的 ;

在这里插入图片描述
在这里插入图片描述

2、次版本号

minor_version ( 次版本号 ) :

2

字节 , 00 00 , 次版本号是

0

; 对应字节码附加信息中的 minor version: 0 ;

在这里插入图片描述
在这里插入图片描述

3、主版本号

major_version ( 主版本号 ) :

2

字节 , 00 34 , 主版本号是

52

; 对应字节码附加信息中的 major version: 52 ;

  • 这个主版本号
52

对应 JDK 版本的

1.8

版本 ;

51

对应

1.7

;

53

对应

1.9

;

45

对应

1.0

;

在这里插入图片描述
在这里插入图片描述

4、常量池个数

constant_pool_count ( 常量池个数 ) :

2

字节 , 00 15 , 常量池个数是

21

个 ; 由于 JVM 占用了默认的常量池 #0 , 因此实际上的常量个数是

21 - 1

个 , 需要对这个数减一处理 ;

在这里插入图片描述
在这里插入图片描述

字节码附加信息中 常量池参考 , 有

20

个常量池 ; #0 常量池 , 被 JVM 占用了 , 代表了一个空引用 , 不指向任何位置 ;

代码语言:javascript
复制
Constant pool:
   #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#18         // Student.name:Ljava/lang/String;
   #3 = Class              #19            // Student
   #4 = Class              #20            // java/lang/Object
   #5 = Utf8               name
   #6 = Utf8               Ljava/lang/String;
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               getName
  #12 = Utf8               ()Ljava/lang/String;
  #13 = Utf8               setName
  #14 = Utf8               (Ljava/lang/String;)V
  #15 = Utf8               SourceFile
  #16 = Utf8               Student.java
  #17 = NameAndType        #7:#8          // "<init>":()V
  #18 = NameAndType        #5:#6          // name:Ljava/lang/String;
  #19 = Utf8               Student
  #20 = Utf8               java/lang/Object
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、字节码文件 与 JVM
  • 二、字节码文件示例
  • 三、字节码文件二进制结构分析
    • 1、魔数
      • 2、次版本号
        • 3、主版本号
          • 4、常量池个数
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档