您的位置:1010cc时时彩经典版 > 1010cc时时彩经典版 > 1010cc时时彩经典版Class文件的结构,JAVA虚拟机入

1010cc时时彩经典版Class文件的结构,JAVA虚拟机入

发布时间:2019-08-17 23:27编辑:1010cc时时彩经典版浏览(102)

    读《深远领会Java设想机》有感——第一有些:Class文件的构造,

    1.产生

             源码(.java文件)——>编译器(如:javac)——>字节码(.class文件)——>虚拟机(如:HotSpot)执行

     

    2.Class文件

               1)构成:

               2)例子:

                        [1] .java文件

                                  桌面/test/test/Father.java、桌面/test/test/Father_interface.java、桌面/test/Son.java  ;                     

                        [2]编译出.class文件

                                   cd  桌面/test;  

                                        桌面/test>javac  Son.java;

                        [3]查看.class文件

                                        桌面/test>javap -verbose  Son;

     

    Classfile /C:/Users/Administrator/Desktop/test/Son.class
      Last modified 2016-4-11; size 1005 bytes
      MD5 checksum 7d138d76267a6bb372eba05296e2c932魔数
      Compiled from "Son.java"
    public class test.Son extends test.Father implements test.Father_interface索引(1类索引、2父类索引、3接口索引,指向常量池)
      SourceFile: "Son.java"
      minor version: 0
      major version: 51主板本号
      flags: ACC_PUBLIC, ACC_SUPER访问标志<当前类>
    Constant pool:常量池
       #1 = Methodref          #16.#33        //  test/Father."<init>":()V   符号引用{
       #2 = Fieldref           #15.#34        //  test/Son.sId_literal:I    
       #3 = Fieldref           #35.#36        //  java/lang/System.out:Ljava/io/PrintStream; 
       #4 = Class              #37            //  java/lang/StringBuilder   
       #5 = Methodref          #4.#33         //  java/lang/StringBuilder."<init>":()V
       #6 = String             #38            //  statical_sId =
       #7 = Methodref          #4.#39         //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Strin
    gBuilder;
       #8 = Fieldref           #15.#40        //  test/Son.statical_sId:I
       #9 = Methodref          #4.#41         //  java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      #10 = Methodref          #4.#42         //  java/lang/StringBuilder.toString:()Ljava/lang/String;
      #11 = Methodref          #43.#44        //  java/io/PrintStream.println:(Ljava/lang/String;)V
      #12 = String             #45            //  Son实例构造器!
      #13 = String             #46            //  hello!this is son!
      #14 = String             #47            //  Son类构造器<clinit>执行!
      #15 = Class              #48            //  test/Son 1
      #16 = Class              #49            //  test/Father 2
      #17 = Class              #50            //  test/Father_interface 3    }符号引用
      #18 = Utf8               final_sId   
      #19 = Utf8               I
      #20 = Utf8               ConstantValue
      #21 = Integer            123 字面量
      #22 = Utf8               statical_sId
      #23 = Utf8               sId_literal
      #24 = Utf8               sId_nonLiteral
      #25 = Utf8               <init>
      #26 = Utf8               ()V
      #27 = Utf8               Code
      #28 = Utf8               LineNumberTable
      #29 = Utf8               sayHello
      #30 = Utf8               <clinit>
      #31 = Utf8               SourceFile
      #32 = Utf8               Son.java       符号引用{
      #33 = NameAndType        #25:#26        //  "<init>":()V
      #34 = NameAndType        #23:#19        //  sId_literal:I
      #35 = Class              #51            //  java/lang/System
      #36 = NameAndType        #52:#53        //  out:Ljava/io/PrintStream;
      #37 = Utf8               java/lang/StringBuilder
      #38 = Utf8               statical_sId =
      #39 = NameAndType        #54:#55        //  append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      #40 = NameAndType        #22:#19        //  statical_sId:I
      #41 = NameAndType        #54:#56        //  append:(I)Ljava/lang/StringBuilder;
      #42 = NameAndType        #57:#58        //  toString:()Ljava/lang/String;
      #43 = Class              #59            //  java/io/PrintStream
      #44 = NameAndType        #60:#61        //  println:(Ljava/lang/String;)V
      #45 = Utf8               Son实例构造器!   }符号引用
      #46 = Utf8               hello!this is son!
      #47 = Utf8               Son类构造器<clinit>执行!
      #48 = Utf8               test/Son
      #49 = Utf8               test/Father
      #50 = Utf8               test/Father_interface
      #51 = Utf8               java/lang/System
      #52 = Utf8               out
      #53 = Utf8               Ljava/io/PrintStream;
      #54 = Utf8               append
      #55 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
      #56 = Utf8               (I)Ljava/lang/StringBuilder;
      #57 = Utf8               toString
      #58 = Utf8               ()Ljava/lang/String;
      #59 = Utf8               java/io/PrintStream
      #60 = Utf8               println
      #61 = Utf8               (Ljava/lang/String;)V
    {
      public test.Son();方法表——实例构造器
        flags: ACC_PUBLIC
        Code:
          stack=3, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method test/Father."<init>":()V
             4: aload_0
             5: bipush        123
             7: putfield      #2                  // Field sId_literal:I
            10: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
            13: new           #4                  // class java/lang/StringBuilder
            16: dup
            17: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
            20: ldc           #6                  // String statical_sId =
            22: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/
    lang/StringBuilder;
            25: getstatic     #8                  // Field statical_sId:I
            28: invokevirtual #9                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilde
    r;
            31: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
            34: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            37: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
            40: ldc           #12                 // String Son实例构造器!
            42: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            45: sipush        333
            48: putstatic     #8                  // Field statical_sId:I
            51: return
          LineNumberTable:
            line 15: 0
            line 7: 4
            line 16: 10
            line 17: 37
            line 18: 45
            line 19: 51
    
      public void sayHello();方法表——sayHello()
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=1, args_size=1
             0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
             3: ldc           #13                 // String hello!this is son!
             5: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
             8: return
          LineNumberTable:
            line 21: 0
            line 22: 8
    
      static {};方法表——类构造器(或静态代码块)
        flags: ACC_STATIC
        Code:
          stack=3, locals=0, args_size=0
             0: bipush        123
             2: putstatic     #8                  // Field statical_sId:I
             5: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
             8: new           #4                  // class java/lang/StringBuilder
            11: dup
            12: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
            15: ldc           #6                  // String statical_sId =
            17: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/
    lang/StringBuilder;
            20: getstatic     #8                  // Field statical_sId:I
            23: invokevirtual #9                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilde
    r;
            26: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
            29: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            32: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
            35: ldc           #14                 // String Son类构造器<clinit>执行!
            37: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            40: return
          LineNumberTable:
            line 6: 0
            line 11: 5
            line 12: 32
            line 13: 40
    }
    

     

     

     

              3.总结         

    魔数、版本号、常量池、访谈标记、索引、字段表会集、方法表会集

    魔数 版本号 常量池 访问标志 索引 字段表集合 方法表集合

    后缀名是可以改的,

    所以用它来确定真

    的是.class文件

    44=JDK1.0

    45=jdk1.1

    ....

    字面量:int、double等基本类型数据值

    符号引用:(最终指向UTF-8字符串)

         1)记录类

                    访问标志 全限定名              

         2)记录方法

                    简单名称 返回类型 参数列表

         3)记录成员属性

                    简单名称 返回类型

     

     

    分为:本类、继承父类类、实现接口

    指向“常量池—记录类”

     

    每张表:

         访问标志、(名称、描述【如:返回类型、参数等】)、附加属性attributes(Code属性表、Linumber属性表、局部变量表、异常表等)

     /** 括号中表示是指向“常量池”*/

     

     

     

     

    1.产生 源码(.java文件)编译器(如:javac)字节码(.class文件)虚拟机(...

    2.java的支付与运作条件

    付出条件:JDK(Java Delelopment Kit)把源码编写翻译成字节码
    jdk1.0 -jdk1.1- ... -jdk1.5(改名为jdk5)- jdk6 -jdk7-jdk8
    运转条件:JRE(Java Runtime Environment)推行字节码
    虚构机运营字节码

    ConstantValue属性

    ConstantValue属性的法力是通报设想机自动为静态变量赋值。独有被static关键字修饰的变量才干够使用那项属性。对于非static类型的变量的赋值时在实例构造器<init>方法中开始展览的,而对于类变量,有二种艺术可选用,赋值在类的布局器<clinit>方法中举行,恐怕利用ConstantValue属性来赋值。前段时间Sun javac编写翻译器选用是:假如还要利用static和final来修饰三个变量,况且这些变量的数据类型是宗旨项目或然是String类型的话,就生成ConstantValue属性来举办早先化,假若那一个变量并不曾被final修饰,可能是非基本数据类型及字符串类型,则选取在<clinit>方法中举办初阶化。
    尽管有final关键字才更合乎ConstantValue的语义,但虚拟机标准中并不曾请只要求字段必须设置ACC_FINAL标记,只供给ConstantValue属性的字段必须设置ACC_STATIC标识,对final关键字的供给是javac编写翻译器自身投入的范围。ConstantValue属性的构造如下:

    1010cc时时彩经典版 1

    ConstantValue

    第二点表明了Class文件选取无符号数和表来积攒数据,不过具体怎么积攒呢?储存的条条框框是何等啊?

    1.流程

    • 创建 HelloWorld.java
      代码如下
      package jvm;

        /**
         * @author lidiqing
         * @since 2017/3/4.
         */
        public class HelloWorld {
      
            private final String text = "Hello World!";
      
            public HelloWorld() {
            }
      
            public String getText() {
                return text;
            }
        }
      
    • 编译成 HelloWorld.class

    • 使用 javap -version HelloWorld.class输出字节音讯

      1010cc时时彩经典版 2

      javap输出

    • 运用 winhex 查看二进制数据

      1010cc时时彩经典版 3

      winhex输出

    4.配备相关知识

    境况变量的布置:

    path系统用来钦定jdk的bin路线。当在CMD中实施命令时,无需步入到bin文件中,因为中间有大多可推行文件(javac.exe、java.exe)。能够直接在CMD使用java、javac等一声令下。
    classpath点名程序中所使用的类公事所在的任务(如若你想要编写翻译在当前目录下找,就增进“.”,如:.;C:Program FilesJavajdklib)

    bin文件夹下的常用可实行文件:

    javadoc.exe:把团结写的源代码文件生成援助文书档案,java文件中必将在有public类和文书档案注释
    cmd执行:javadoc 源码.java
    jar.exe:把相关字节码文件(.class)生成二个jar压缩包
    cmd执行:jar cfv xxx.jar xxx.class xxx.class (.class全数的文书)*

    java注释://  /*  */ 
    文档注释:/**  */
    

    常量池

    紧接着是常量池入口。常量是Class文件空间最大的数目项目之一。常量池容积为u2数据类型,其索引值是从1先河的,比如0x0016为十进制22,但事实上独有21(1~21)个常量。常量池中索引为0代表不援引任何常量。Class文件中唯有常量池索引是从1开首的,别的的都与一般习于旧贯一样,从0起首。
    常量池主要寄放两类常量:字面常量和标识引用。字面常量如文本字符串、被声称为final的常量值。而符号援引常量包蕴下边三类常量:

    • 类和接口的全限定名
    • 字段的名目和陈述符(Descriptor)
    • 艺术的称呼和陈说符
      Class文件加载的经过中虚构机必要依赖目录去常量池分析对应的值。
      常量池中各种常量都以三个表,共有1第11中学各不一致的表结构数据,这几个表结构皆有三个特点就是率先位是一个u1项指标标识位,代表常量类型。

    1010cc时时彩经典版 4

    CONSTANT_Class_info的构造首要包罗 u1(表示常量类型) u2(name_index) name_index是三个索引值,它指向常量池中三个CONSTANT_Utf8_info类型的常量,此常量代表了这一个类依旧接口的全限定名。
    CONSTANT_Utf8_info的构造为u1(tag) u2(length) u1(bytes)(length 个), 个中length字段表明那么些utf-8编码的字符串的尺寸是有一点字节,它背后紧跟着的长短为length字节的连日数据。utf-8编码中从'u0001'到'u007f'之间的字符的缩略吗使用二个字节表示,从'u0080'到'u07ff'之间的具备字符的缩略编码用四个字节表示。从'u0800'到'uffff'之间的持有字符缩略码使用四个字节表示。大家利用javap -verbose 能够将字节码内容打字与印刷出来。
    常量池中数据类型的布局如下:

    1010cc时时彩经典版 5

    1010cc时时彩经典版 6

    常量池后边是u2意味做客标记(access_flags),这么些标记用于标记当前class的一部分类还是接口等级次序的访问音信。具体如下:

    1010cc时时彩经典版 7

    this_class 和 super_class都以三个u2索引类型,用于标志类和父类的全限定名。interfaces用于标记接口集合。

    Class文件的前4个字节称为魔数,是用以分明这么些文件是还是不是是可以被java虚构机接受的.class文件,为啥不用后缀名来判定呢?当然是因为

    2.3.1 概述

    特点:

    • Class 文件的财富货仓
    • Class 文件仲春其余项目涉及最多
    • Class 文件中最大的数目项目之一

    重在品种:

    • 字面量,语言层面包车型客车常量,如文本字符串,final常量(如字符串 'HelloWorld!')
    • 标记援引,编写翻译层面包车型地铁常量
      • 类和接口的全限定名(如 jvm/HelloWorld
      • 字段的称谓和陈说符 (如 jvm/Helloworld/text:Ljava/lang/String;)
      • 办法的名号和陈说符(如 java/lang/Object."<init>":()V

    作用:

    任由字段表、方法表还是属性表,只要涉及到有的常量只怕描述,都会有个目录指向该表的某部地点

    3.Java分类

    java程序:

    applet程序 (没落了)
    java application(java 应用程序):
    javaSE:java标准版本
    javaEE:java 集团级应用程序
    javaME:java桌面应用程序(被android代替)

    Deprecated及Synthetic属性

    那多个属性都以布尔型属性,Deprecated一般对应于代码中@deprecated注释。Synthetic属性代表此字段或措施并非由Java源码直接产生的,而是由编写翻译器自行增添的。自Java1.5随后能够设置访谈标记中的ACC_SYNTHETIC标记位,全部非用户代码生成的类,方法及字段都应该至少设置Synthetic属性和ACC_SYNTHETIC标识位中的二个。独一的两样是<init>和<clinit>

    (四)访谈标记(2个字节)

    2.7 方法表集结

    1.Java代码运转原理

    源代码文件(.java)——>java编译器(javac.exe)编译——>
    字节码文件(.class)——>java解释器(java.exe)运作——>虚构机实施
    cmd实践措施:
    编译:javac 源文件.java //一个源码中如果有多少个类就生成多少个.class文件
    执行:java 类名 //如果源码修改了,要重新编译
    虚构机:JVM(Java Virtual Machine)能够兑现跨平台运转,因为不相同的阳台(操作系统)有区别的虚构机,不过同样份字节码在不一样的虚构机的运行结果是一律的。

    魔数与Class文件的本子

    Class文件的前4个字节为魔数,为0xCAFEBABE,紧接着4个字节存款和储蓄的是Class文件的本子号,第五第五个字节是次版本号,第七第五个是主版本号。高版本的JDK能向下包容在此之前版本的Class文件,但无法裕兴现在版本的Class文件,纵然文件格式未产生变化。

    1010cc时时彩经典版 8

    2.8 属性表群集

    属性表(attribute_info)集合

    与class文件中别的的数码项须要从严的各类、长度和内容见仁见智,属性表并不要求各类属性有严格的逐个,而且只要不与已知的习性名重复就可以。任何人实现的编写翻译器都足以向属性表中写入自个儿定义的属性消息,Java虚构机运营时会忽略掉它不认得的质量。为了能正确地深入分析class文件,设想机应当识别的性质如下:

    1010cc时时彩经典版 9

    属性表中最少定义的字段

    对此每一种属性它的称谓它的称谓为u2的索引类型,而属性值的协会则是完全自定义的,只需求证明属性值所占领的位长度就可以。其主要字段包蕴:u2(attribute_name_index) u2(attribute_length) u1(info)

    二:Class文件结构概述

    2.7.3 表

    方法表(method_info):

    类型 名称 数量
    u2 access_flags 1
    u2 name_index 1
    u2 descriptor_index 1
    u2 attributes_count 1
    attribute_info attributes attributes_count

    办法访谈标记(access_flag):

    标志名称 标志值 含义
    ACC_PUBLIC 0x0001 是否为 public
    ACC_PRIVATE 0x0002 是否为 private
    ACC_PROTECTED 0x0004 是否为 protect
    ACC_STATIC 0x0008 是否为 static
    ACC_FINAL 0x0010 是否为 final
    ACC_SYNCHRONIZED 0x0020 是否为 synchronized
    ACC_BRIDGE 0x0040 是否为编译器产生的桥接方法
    ACC_VARARGS 0x0080 是否接受不定参数
    ACC_NATIVE 0x0100 是否为 native
    ACC_ABSTRACT 0x0400 是否为 abstract
    ACC_STRICTFP 0x0800 是否为 strictfp
    ACC_SYNTHETIC 0x1000 是否为编译器自动产生的

    LineNumberTable属性

    一言九鼎用以描述Java源代码行号与字节码行号之间的呼应关系。它实际不是运作时务必的属性,但私下认可会生成到Class文件之中,能够在Javac中运用-g:none 或-g:lines选项来撤废或要求扭转那项音讯。其格式如下:

    1010cc时时彩经典版 10

    line_number_table是二个数目为line_number_table_length 类型为line_number_info的集合,line_number_info表满含了start_pc和line_number三个u2项指标数目项,前面二个是字节码行号,前面一个是Java源码行号。

    世家也大概注意到,在介绍常量池的时候,小编用了“不定个字节”,表明常量池的字节长度是不分明的。这怎么分明常量池到底是到哪个地方呢?那取决于常量池

    2.7.2 数据深入分析

    1010cc时时彩经典版 11

    方法表集结二进制数据

    • methods_count => 0x0002
      意味着该类有七个办法

    • methods
      分别有三个主意,都以 method_info 的结构。methods_count 紧接着正是首先个方法表
      今昔只解析第三个方法表
      access_flag => 0x0001
      方法为 Public 方法
      name_index => 0x0009
      方式名叫常量表第9个常量,是 Utf8 类型,为 “<init>”,所以那么些方式是类的初叶化方法

        Constant pool
            #9 = Utf8       <init>  
      

    descriptor_index => 0x000A
    艺术描述符为常量表第12个常量,也是 Utf8 类型,为 “()V”

        Constant pool
            #10 = Utf8      ()V    
    

    attribute_count => 0x0001
    品质数据为 1。从那些能够,该情势有叁天品质。
    差不离全部办法都至少有一个属性 “Code” 用来记录格局中编译后的字节码指令。也能够说,方法中的代码编写翻译成字节码指令后都被存入了 “Code” 属性中了
    attribute_name_index => 0x000B
    常量表第10个常量,也是 Utf8 类型,正是 “Code” 属性

        Constant pool
            #11 = Utf8      Code    
    

    attribute_length => 0x0000003D
    表示接下去的 29 个字节正是 “Code” 属性表的剧情了,关于那些属性表的深入分析在末端
    利用 javap 能够得出详细的深入分析结果如下:

    1010cc时时彩经典版 12

    javap的辨析结果

    类中字段

    field_info 用于描述接口或类中扬言的变量。包涵静态和非静态的变量。字段表的组织如下:

    1010cc时时彩经典版 13

    其中name_index描述字段名称 descriptor描述的是字段的呈报符(这么些类似jni中的描述类似)attribute_info是字段的附加描述音讯。
    filed_info中不会列出承袭来的字段,但有希望会列出原来java代码中不设有的字段,譬喻内部类会增加指向外界类的字段。

    (二)表

    2.8.3.3 LocalVariableTable 属性

    用处

    • 呈报栈帧局地变量表中的变量和 Java 源码中对应的变量之间的关系
    • 可利用 -g:none 或 -g:vars 来撤消大概生产那项音信
    • 从没该属性,当其余人援引这么些法子,全体的参数名称错失,IDE 会使用 arg0、arg1 等占位符代替

    LocalVariableTable 具体的结构为

    类型 名称 数量
    u2 attribute_name_index 1
    u4 attribute_length 1
    u2 local_variable_table_length 1
    local_variable_info local_variable_table local_variable_table_length

    local_variable_1010cc时时彩经典版,info 的组织为

    类型 名称 数量
    u2 start_pc 1
    u2 length 1
    u2 name_index 1
    u2 descriptor_index 1
    u2 index 1

    用第贰个措施表的 code 属性的 LocalVariableTable 属性数据来分析

    1010cc时时彩经典版 14

    先是个方法表的 code 属性的 LocalVariableTable 属性的二进制数据

    • attribute_name_index => 0x000D
      针对常量池第 13 个常量,能够识破就是 “LocalVariableTable”

    • attribute_length => 0x0000000C
      性格的长度为 12,所以接下去 12 个字节都以 LocalVariableTable 属性的值

    • local_variable_table_length => 0x0001
      代表接下去有一个 local_variable_info 用来代表栈帧内一些变量表和源码的涉及

    • local_varibale_info
      start_pc => 0x0000
      该部分变量的生命周期起头的字节码偏移量
      length => 0x000B
      该片段变量的生命周期作用范围的长度
      为此该部分变量作用在 0 -> 11 条字节码之间,可见为一切艺术的字节码指令集范围内
      name_index => 0x000E
      本着常量池第 14 个常量,为 “this”,所以这些局部变量是 this 指针,指向使用该方式的近年来实例
      descriptor_index => 0x000F
      本着常量池第 15 个常量,为 “Ljvm/HelloWorld”,所以那一个 this 指针代表的正是类 HelloWorld 的实例
      index => 0x0000
      表示该部分变量在栈帧局地变量表中 Slot 的职位,可见为率先个 Slot

    SourceFile属性

    用以记录生成那一个Class文件的源码文件名称。这一个天性也是可选的。对于大好多类来讲,类名和文书名是均等的,不过里面类除了那么些之外。若无那特性子,当抛出极度的时候,旅馆中不会显得出错误代码所属的文本名,其布局如下:

    1010cc时时彩经典版 15

    SourceFile

    的,用于末端指向常量池的目录数据在特定情景下公布“不援用任何二个常量池项目”的意趣,这种情状下将索引值置为0(也正是常量池第二个字节)就行了。

    2.8.1 概述

    下边已经有用到三种属性,字段用到 constantvalue 用来代表是三个常量,方法用到了 code 来记录格局的字节码指令集合

    特点:

    • 属性不须求严苛按顺序排列,只要不重名
    • 属性值的布局可完全自定义,但设想机只取自个儿认知的

    InnerClasse

    笔录内部类与宿主类之间的涉嫌。其属性表结构如下:

    1010cc时时彩经典版 16

    InnerClass

    其中inner_classes_info表的构造如下:

    1010cc时时彩经典版 17

    inner_classes_info

    utf8字符串攻陷的字节数是拾九个字节,也正是从6A直接到下一行的74,那14个字节代表的就是全限定名常量的名字。这里就涉及到怎么翻译utf8缩

    2.1 Class 文件格式

    LocalVariableTable属性

    用来描述栈帧中部分变量表中的变量与Java源码中定义的变量之间的关联,他们不是运作时务必的属性,暗中同意也不会转移到Class文件中。若无成形那特性格,最大的影响是当其余援引这么些方法时,全体的参数名称都将错失,IDE可能会采纳arg0、arg1等来代替本来的参数名。
    其属性表如下:

    1010cc时时彩经典版 18

    LocalVariableTable

    local_variable_info的结构如下所示:

    1010cc时时彩经典版 19

    local_variable_info

    start_pc和length属性分别代表了那个片段变量的生命周期开首的字节码偏移量及其功用范围覆盖的长度。name_index和descriptor_index都以指向常量池中CONSTANT_Utf8_info型常量的目录,分别表示了一部分变量的名目及该有的变量的描述符。
    index是以此片段变量在栈帧局地变量中slot的职责,当这几个变量的数据类型是61个人类型时,它占用的slot为index和index 1七个地方。

    任由是什么语言,只要对应的编写翻译器能够将程序代码编写翻译成Class文件,java虚构机并不在乎到底Class文件是由哪些得来的,只要它符合Class文件结构的要求,就能够在java设想机中运作。

    2.6.1 概述

    限制:包括类级、实例级变量,不包蕴方法内部宣称的一部分变量

    信息:

    选择标记表示

    • 作用域
      • public
      • private
      • protect
    • static 实例变量依然类变量
    • final 可变性
    • volatile 并发可知性
    • transient 可被系列化

    用常量表示

    • 字段数据类型(基本项目、对象、数组)
    • 字段名称

    Class类文件的结构

    Class文件是一组以8位为根基单位的二进制流,当须求暂用8位字节以上空间的数量时,则会服从高位在前的措施划分成几何个8位字节举行仓库储存。
    基于Java虚构机标准的规定,Class文件格式选拔一种恍若于C语言结构体的伪结构来囤积。包括两种数据类型:无符号数和表。在那之中无符号数属于基本的数据类型,以u1 u2 u4 u8 分别表示1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引援用,数量值,或然依据啊UTF-8编码构成字符串。表是由四个无符号数或其余表作为数据项整合的复合数据类型,表习于旧贯性以_info结尾。无论是无符号数依然表,当必要描述同一类型但数目不定的多少个数据时,日常会选择二个置于的容积计数器加若干接二连三的多少项的款式。

    1010cc时时彩经典版 20

    本来,这些java项目比较大约,独有二个类,

    2.2.1 概述

    • 魔数
      唯一功用:确认该文件能被虚构机接受
      类加载进度中的验证阶段,会推断该 Magic

    • 版本号和编写翻译器 JDK 有关

    Exceptions属性

    Exceptions 属性功用是列举出艺术中只怕抛出的受检查非凡。其结构表如下:

    1010cc时时彩经典版 21

    此属性中的number_of_exceptions项表示方法大概抛出number_of_exceptions中受检分外,种种受检查的丰富使用二个exception_index_table项表示。

    接下去就耐心地对表里的各个进行详细表明。

    2.5 索引集结

    Code属性

    无须全部的不二等秘书技都必须有那本性情,举个例子接口或抽象类中的方法就不设有Code属性。Code属性的构造如下:

    1010cc时时彩经典版 22

    Code的属性

    attribute_length 提醒了属性值的长短,由于本性名称索引和属性长度移动是6个字节,所以属性值的长度固定为一体属性表的尺寸减去6个字节。
    max_stack代表了操作数栈深度的最大值。在施行狂妄指令的时候操作数栈都不会超过那几个深度。虚构机械运输转的时候须要基于那么些值来分配栈中操作栈的纵深。
    max_locals代表了部分变量表所急需的积累空间。在那边max_locals单位是slot,slot是设想机为局地变量分配内存所使用的纤维单位。对于byte,char,float,int,short,bootlean,reference,returnAddress等长短不超越三十八位的数据类型,各个局地变量占用1个slot,而double和long那三种六十人的数据类型则要求2个slot.方法参数、显式十分管理器的参数、方法体中定义的片段变量需求动用部分变量表来存放。不过而不是情势中央银行使的一部分变量的总量作为max_locals,因为一些变量表中的slot能够被重复使用。编写翻译器会依据变量的成效域来分类slot并分配给各种变量使用,然后总结出max_locals的大小。
    code_length 和 code用来存款和储蓄字节码指令。code中每一条指令都以u1品类,一共能够公布256条指令,方今java虚构机标准已经定义了约200条指令的含义。由于code_length 是u4类别不过设想机限制三个办法中不容许超越65535条指令,假如赶过java编写翻译器会拒绝编写翻译。
    在字节码指令之后的是那一个艺术的显式的万分管理表集结,格外表包蕴七个字段:假诺字节码从第start_pc行到第end_pc行之间出现了花色为catch_type或其子类的要命(catch_type为指向三个CONSTANT_Class_info型常量的目录)则转到handler_pc行继续管理。当catch_type为0是代表任何至极情状都要转向handler_pc处实行管理。相当表格式如下:

    1010cc时时彩经典版 23

    异常表

    格外表实际上是Java代码的一部分,编写翻译器使用极度表并不是差不离的跳转命令来兑现Java分外及finallly管理机制。

    常量池中的常量首要包含两大类:Leteral和符号引用(Symbolic Reference)。Literal类似于java描述的常量,如文本字符串,final修饰的档期的顺序。符号引用主要不外乎三类常量:

    2.3.2 数据剖判

    在 class 中的二进制数据

    1010cc时时彩经典版 24

    常量池的二进制数据

    • constant_pool_count => 0x19
      体量计数,常量表从 1 发轫计数,所以 0x19 独有 0x18 个常量,十进制 二十九个常量
      那样的话,借使因为另各地方用了目录为 0,常量为空,比方java.lang.Object 对象是全数类的基类,父索引为 0

    • constant_pool
      对照 2.3.3 的常量池结果总表来开始展览解析,直接用 javap 输出 贰十七个常量如下

        Constant pool:
           #1 = Methodref          #5.#20         // java/lang/Object."<init>":()V
           #2 = String             #21            // Hello World!
           #3 = Fieldref           #4.#22         // jvm/HelloWorld.text:Ljava/lang/String;
           #4 = Class              #23            // jvm/HelloWorld
           #5 = Class              #24            // java/lang/Object
           #6 = Utf8               text
           #7 = Utf8               Ljava/lang/String;
           #8 = Utf8               ConstantValue
           #9 = Utf8               <init>
          #10 = Utf8               ()V
          #11 = Utf8               Code
          #12 = Utf8               LineNumberTable
          #13 = Utf8               LocalVariableTable
          #14 = Utf8               this
          #15 = Utf8               Ljvm/HelloWorld;
          #16 = Utf8               getText
          #17 = Utf8               ()Ljava/lang/String;
          #18 = Utf8               SourceFile
          #19 = Utf8               HelloWorld.java
          #20 = NameAndType        #9:#10         // "<init>":()V
          #21 = Utf8               Hello World!
          #22 = NameAndType        #6:#7          // text:Ljava/lang/String;
          #23 = Utf8               jvm/HelloWorld
          #24 = Utf8               java/lang/Object    
      

    Methodref,是办法的符号援用,比方虚构机调用 invokespecial 指令会用到,举个例子该类的初叶化方法字节码指令中有与上述同类一条

        1: invokespecial #1
    

    如此会实例化 #1 的方法,而 #1 是 java.lang.Object 的起头化方法,所以该指令实行了 Object 的早先化
    Fieldref,是字段的符号援引,譬喻设想机调用 put田野指令会去剖析该符号引用

        7: putfield #3    
    

    那样的话会把该符号援引对应的变量,设置为栈帧中的值
    NameAndType,字段也许措施的描述,盛名称和呈报符组合起来
    Class,表示一个类的全限定名
    String,表示一个字符串常量
    Utf8,使用 utf-8 格式编码的字符串,最终其余门类的常量都会指向那几个值,那是最大旨的常量值

    Class 文件加载后,常量池的字面量和标识引用会被存入方法区,几个线程分享。方法区又称作永恒带,GC 基本不在方法区进行垃圾回收。但也可能有,比方一些撇下的常量和低效的类

    方法表

    格局表的开始和结果和字段表基本是一样的,依次包含 access_flags name_index decriptor_index attributes.
    艺术里的java代码,经过编写翻译成字节码指令后,存放在情势属性表群集中三个名叫code的性质之中。在java语言中只靠重临值类型差别不能够结成艺术的重载。而在class文件中是能够的。

    1010cc时时彩经典版 25

    2.4.1 概述

    识别类或接口档案的次序的访问讯息

    u2类型=2个字节=15人可用,近些日子只定义了8个,可知前边的拜望标识表

    那现实应该怎么积存呢?Class文件格式选拔了周围于C语言结构体的伪结构实行仓储。这种结构独有二种数据类型:无符号数和表。前边境海关于Class文件的组织深入分析都要树立在那二种数据类型上,由此先解说那二种数据类型。

    2.2.2 数据解析

    1010cc时时彩经典版 26

    魔术和本子对应数据

    • magic
      固定值:0xCAFEBABY

    • minor_version
      次版本号:0x0000

    • major_version
      主版本号:0x0034

    后缀名实在是太轻松改了,而文件格式拟定者只要使用标示文件格式的魔数,而且魔数未有被别的人采取,那就足以起到标示的效用了。Class文件的魔数是

    2.6.2 数据分析

    1010cc时时彩经典版 27

    字段表集结二进制数据

    • fields_count => 0x0001
      有二个字段

    • fields
      从 fields_count 知道独有二个字段,查表能够收获 田野先生_info 各类部分为:
      access_flags => 0x0012=0x0010|0x0002
      基于字段访谈标识可知,这是个 private 和 final 型属性
      name_index => 0x0006
      目录对应常量池第6个常量,名称叫 “text”

        Constant pool
            #6 = Utf8       text    
      

    descriptor_index => 0x0007
    目录对应常量池第7个常量,所以描述符为 “Ljava/lang/String;”

        Constant pool
            #6 = Utf8       Ljava/lang/String;  
    

    attribute_count => 0x0001
    之所以该字段有三特性质,接下去正是事无巨细的 attribute_info 数据,表示该字段的性子
    attribute_name_index => 0x0008
    目录对应常量池第8个常量,属性名为 “constantvalue”

        Constant pool
            #8 = Utf8       constantvalue    
    

    该属性用来打招呼设想机自动为静态变量赋值。这一个发生在类的加载进程中的初叶化阶段。关于类变量,初始化的时候会给暗中认可值,但万一有 Constantvalue 属性,就可以用那么些天性的值来对类变量举行起始化
    attribute_length => 0x00000002
    constantvalue 的该值固定为 2,因为前面须要 u2 类型的多少来针对常量池,表示该 constantvalue 的值
    constantvalue_index => 0x0002,索引对应常量池第四个常量,值为 “Hello World!”

        Constant pool
            #2 = String     #21
            #21 = Utf8      Hello World!    
    

    实质上,用代码实行相比较的话,上边字段对应 Java 源码为

        private final String text = "Hello World!";    
    

    在编写翻译成 class 文件后,大家得以解析到这么的结果

        flags: ACC_PRIVATE ACC_FINAL
        name: text
        descriptor: Ljava/lang/String;
        attributes:
            constantvalue:HelloWorld!
    

    在 Java 中用 static 和 final 修饰的字段,即该类的常量字段。在 Java 编写翻译阶段的常量传播优化中,假诺 B 只援用了 A 的常量,编写翻译后 A 的常量会被转化为 B 的常量,存入 B 类的常量池里。所以,常量传播优化后,使用者 B 就能有所 A 的常量,对 A 常量的援引在 Class 文件中变为对和睦的常量的引用

    (三)常量池(不定个字节)

    2.8.2 基本构造

    类型 名称 数量
    u2 attribute_name_index 1
    u4 attribute_length 1
    u1 info attribute_length

    种种属性的称呼都要从常量池中拿一个 Utf8 类型的常量。属性的始末为 attribute_length 个 info 组成,每一种 info 由二个字节组成。所以属性的重组是很利索的,怎么样讲授那一个info,有虚构机的正统,也能够完全自定义。但设想机在条分缕析的时候,只取本身职业的这有个别

    本文由1010cc时时彩经典版发布于1010cc时时彩经典版,转载请注明出处:1010cc时时彩经典版Class文件的结构,JAVA虚拟机入

    关键词: