可以不用掌握,但必须了解字节码文件的整体结构

319 阅读2分钟

一. 整体结构

ClassFile {
u4             magic; 
u2             minor_version;
u2             major_version;
u2             constant_pool_count;
cp_info        constant_pool[constant_pool_count-1];
u2             access_flags;
u2             this_class;
u2             super_class;
u2             interfaces_count;
u2             interfaces[interfaces_count];
u2             fields_count;
field_info     fields[fields_count];
u2             methods_count;
method_info    methods[methods_count];
u2             attributes_count;
attribute_info attributes[attributes_count];
}

备注:u表示字节数,u4表示4个字节,u2表示2个字节

二. 示例

示例代码:

package com.yu.jvm;
​
public class TestClass {
​
    public static void main(String[] args) {
​
    }
}

使用bined(idea插件)打开class文件:

bined_testclass.png

我们根据16进制字节流和字节码整体结构来对应一下

定义字节码值备注
u4 magicCA FE BA BE所有class的开头都是以CAFE BABE开始
u2 minor version00 00小版本号:0
u2 major version00 34大版本号:52(表示是jdk1.8)
u2 constant_pool_count00 14常量池常量数量是20 - 1 = 19个
cp_info19个常量
u2 access_flags00 21位于0F0行,0C列,0020表示super,0001表示public
u2 this_class00 02表示指向常量池中的第2个常量
u2 super_class00 03指向常量池中第3个常量
u2 interfaces_count00 00表示没有实现接口
u2 interfaces[interfaces_count]00 00空数组
u2 field_count00 00成员变量数量
field_info fields[fields_count]变量信息
u2 methods_count00 022个方法:psvm方法,init方法
method_info methods[methods_count]方法信息
u2 attributes_count00 01属性数量
attribute_info attributes[attributes_count]00 0F属性信息,指向常量池15号

使用javap -v 打开

Classfile /C:/Users//IdeaProjects/TestDemo/out/production/TestDemo/com/yu/jvm/TestClass.class
  Last modified 2022-5-6; size 392 bytes
  MD5 checksum ea651574c357b81298e8df2ce3683d60
  Compiled from "TestClass.java"
public class com.yu.jvm.TestClass
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#17         // java/lang/Object."<init>":()V
   #2 = Class              #18            // com/yu/jvm/TestClass
   #3 = Class              #19            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               LocalVariableTable
   #9 = Utf8               this
  #10 = Utf8               Lcom/yu/jvm/TestClass;
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               args
  #14 = Utf8               [Ljava/lang/String;
  #15 = Utf8               SourceFile
  #16 = Utf8               TestClass.java
  #17 = NameAndType        #4:#5          // "<init>":()V
  #18 = Utf8               com/yu/jvm/TestClass
  #19 = Utf8               java/lang/Object
{
  public com.yu.jvm.TestClass();
    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 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/yu/jvm/TestClass;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=1, args_size=1
         0: return
      LineNumberTable:
        line 7: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       1     0  args   [Ljava/lang/String;
}
SourceFile: "TestClass.java"

使用jclaaslib打开(版本较老)

jclasslib_testclass.png

三. 总结

可以基于上述了解字节码文件的整体结构,对通过javac编译出来的class文件有个大致的认知即可。对于字节码指令,使用方式等等可以在需要的时候可以查看资料了解,java8的字节码文档docs.oracle.com/javase/spec…