欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识
原文出处: 拿笔小星_

这篇博客开始,我规划带各人去解读一下JVM平台下的字节码文件(熟悉而又生疏的感受)。众所周知,Class文件包括了我们界说的类或接口的信息。然后字节码又会被JVM加载到内存中,供JVM利用。那么,类信息到了字节码文件里,它们如何暗示的,以及在字节码里是怎么漫衍的呢?带着这些问题,让我们去深入相识字节码文件吧。

Class文件的布局

Class文件是一组以8位字节为基本单元的二进制流,各个数据项目严格凭据顺序紧凑地分列在Class文件之中,中间没有添加任何脱离符,这使得整个Class文件中存储的内容险些全部是措施运行的须要数据,没有旷地存在。当碰着需要占用8位字节以上空间地数据项时,劳务派遣管理系统,则会凭据高位在前的方法支解成若干个8位字节举办存储。

每一个 Class 文件对应于一个如下所示的 ClassFile 布局体。

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];
}

这种数据布局,雷同C语言布局体。这个布局体中只有两种数据范例:无标记数和表,后头的理会都要以这两种数据范例为基本,所以这里要先先容这两个观念。

无标记数属于根基的数据范例,以u1,u2,u4,u8来别离代表1个字节,2个字节,4个字节和8个字节的无标记数,无标记数可以用来描写数字、索引引用、数量值可能凭据UTF-8编码组成字符串值。

表是由多个无标记数可能其他表作为数据项组成的复合数据范例,所有表都习惯性地以“_info”末了。表用于描写有条理干系的复合布局的数据,整个Class文件本质就是一张表。

下面是我的案例代码,本章将以此代码生成的字节码文件作为例子来阐明。

public class MyTest2 {
    String str = "Welcome";
    private int x = 5;
    public static Integer in = 10;

    public static void main(String[] args) {
        MyTest2 myTest2 = new MyTest2();
        myTest2.setX(8);
        in = 20;
    }

    public void setX(int x) {
        this.x = x;
    }
}

对应生成的字节码文件名目如下:(数据内容较多,只是截了部门)

开始是一 <a href=昆山软件开拓 个符号位" class="aligncenter size-full wp-image-30465" title="20181014145935732" src="/uploads/allimg/c181119/15425G3162C40-1T37.png" />

上面的数字是以16进制暗示的。我们可以凭据之前的布局一项项去解读它。

Class文件理会

magic

魔数,u4范例的数据,占4个字节。魔数的独一浸染是确定这个文件是否为一个能被虚拟机所接管的 Class 文件。魔数值牢靠为 0xCAFEBABE(咖啡宝物),不会改变。

minor_version、major_version

紧接着魔数之后的4个字节为Java版本信息:第5和第6个字节是次版本号(minor_version),第7和第8个字节是主版本号(major_version)。

就看当前这个字节码,次版本号是0×0000=0,主版本号是0×0034=52。我当地呆板用的是JDK1.8,所以可生成的Class文件主版本号最大值为52.0。

下面给出了Java各个主版本号,以供参考。

开始是一 <a href=昆山软件开拓 个符号位" class="aligncenter size-full wp-image-30464" title="Snipaste_2018-11-18_20-12-02" src="/uploads/allimg/c181119/15425G316323F-253Q.png" />

constant_pool_count

常量池计数器,u2范例的数据。它是常量池的进口,暗示紧随着它后头的常量池的元素个数。算一下,0x002F=47,即常量池里的元素有47个。这里我用jdk的内置东西javap,反编译一下,可以输出常量池的信息以及元素个数。执行呼吁:javap -verbose。输出功效如下:

Constant pool:
   #1 = Methodref          #10.#34        // java/lang/Object."<init>":()V
   #2 = String             #35            // Welcome
   #3 = Fieldref           #5.#36         // com/shengsiyuan/jvm/bytecode/MyTest2.str:Ljava/lang/String;
   #4 = Fieldref           #5.#37         // com/shengsiyuan/jvm/bytecode/MyTest2.x:I
   #5 = Class              #38            // com/shengsiyuan/jvm/bytecode/MyTest2
   #6 = Methodref          #5.#34         // com/shengsiyuan/jvm/bytecode/MyTest2."<init>":()V
   #7 = Methodref          #5.#39         // com/shengsiyuan/jvm/bytecode/MyTest2.setX:(I)V
   #8 = Methodref          #40.#41        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #9 = Fieldref           #5.#42         // com/shengsiyuan/jvm/bytecode/MyTest2.in:Ljava/lang/Integer;
  #10 = Class              #43            // java/lang/Object
  #11 = Utf8               str
  #12 = Utf8               Ljava/lang/String;
  #13 = Utf8               x
  #14 = Utf8               I
  #15 = Utf8               in
  #16 = Utf8               Ljava/lang/Integer;
  #17 = Utf8               <init>
  #18 = Utf8               ()V
  #19 = Utf8               Code
  #20 = Utf8               LineNumberTable
  #21 = Utf8               LocalVariableTable
  #22 = Utf8               this
  #23 = Utf8               Lcom/shengsiyuan/jvm/bytecode/MyTest2;
  #24 = Utf8               main
  #25 = Utf8               ([Ljava/lang/String;)V
  #26 = Utf8               args
  #27 = Utf8               [Ljava/lang/String;
  #28 = Utf8               myTest2
  #29 = Utf8               setX
  #30 = Utf8               (I)V
  #31 = Utf8               <clinit>
  #32 = Utf8               SourceFile
  #33 = Utf8               MyTest2.java
  #34 = NameAndType        #17:#18        // "<init>":()V
  #35 = Utf8               Welcome
  #36 = NameAndType        #11:#12        // str:Ljava/lang/String;
  #37 = NameAndType        #13:#14        // x:I
  #38 = Utf8               com/shengsiyuan/jvm/bytecode/MyTest2
  #39 = NameAndType        #29:#30        // setX:(I)V
  #40 = Class              #44            // java/lang/Integer
  #41 = NameAndType        #45:#46        // valueOf:(I)Ljava/lang/Integer;
  #42 = NameAndType        #15:#16        // in:Ljava/lang/Integer;
  #43 = Utf8               java/lang/Object
  #44 = Utf8               java/lang/Integer
  #45 = Utf8               valueOf
  #46 = Utf8               (I)Ljava/lang/Integer;