栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JVM大作业1.2 字节码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM大作业1.2 字节码

首先声明,本篇文章学习自深入理解JVM之Java字节码(.class)文件详解 - 简书 (jianshu.com)

以下仅为自我整理:

1.每个类或者接口都单独占据着一个class文件

2.class文件中的信息是一项一项排列的。

重点:IMPORTANT

class文件的结构

class文件可以被分为十个部分,有:

MagicNumber,Version,Constant_pool,Access_flag,This_class,Super_class,Interfaces,Fields,Methods 和Attributes

  1. magic
    1. 在class文件的开头的四个字节,此魔数是class文件的标志,是固定的值:0xCAFEBABE.它的作用主要就是来判断这个文件是不是class文件。
  2. minor_version & major_version
    1. 接着的四个字节是class文件的此版本号与主版本号。其他好像没有什么重要的。
  3. constant_pool
    1. very very important:常量池。其中存放了文字字符串,常量值,当前的类名,字段名,方法名,哥哥字段和方法的描述符,对当前类的字段和方法的引用信息,当前类中对其他类的引用信息等。class文件中的很多其他部分都是对常量池中的数据项的引用。字节码指令也存在对常量池的引用(作为一个操作数),常量池中的各个项也会相互引用。
    2. 常量池是一个勒的结构与索引,对对象的调用可以通过索引位置来代替。想要快速的获取某个变量常用的方法是通过索引变量,可以直观理解成“内存地址的虚拟”(这边好像不太懂)。
    3. 之所以称之为静态池:是因为这里维护者经过编译之后的相对固定的数据索引。
    4. constant_pool_count = 1,每个类只有一个常量池。常量池中的每个数据都是通过索引得到的,类似于数组,不过常量池的第一项索引为1而不是0.
    5. 每个数据叫做一个XXX_INFO项。每个info对应这一种tag,表示了info项的类型。(具体见上图)
  4. acesss flag
    1. 保存当前类的访问权限
  5. this_cases
    1. 保存当前类的全局限定名在常量池中的索引
  6. super_class
    1. 保存当前类的父类的全局限定名在常量池中的索引
  7. interfaces
    1. 保存当前类实现的接口列表。
    2. interfaces_count :当前类实现的接口数目
    3. interfaces[] :包含count个接口的全局限定名的索引的数组
  8. fields
    1. 保存当前类的成员列表(static修饰的成员)
    2. fields_count:类变量和实例变量的字段的数量总和
    3. fields[] :包含字段详细信息的列表
  9. methods
    1. 保存当前类的方法列表
    2. methods_count :该类活接口显示定义的方法的数量
    3. methods[] :包含方法信息的一个详细列表
  10. attributes
    1. 包含当前类的attributes列表
    2. class文件的最后一部分是属性,它描述了该类或者接口所定义的一些属性信息。attributes_count指的是attributes列表中包含的attribute_info的数量。
      属性可以出现在class文件的很多地方,而不只是出现在attributes列表里。如果是attributes表里的属性,那么它就是对整个class文件所对应的类或者接口的描述;如果出现在fileds的某一项里,那么它就是对该字段额外信息的描述;如果出现在methods的某一项里,那么它就是对该方法额外信息的描述。

(自己操作不了,就截一个图啦)

1.  

2. 

3. 常量池包含的常量的数目,常量池包含 1 * 16 + 2 - 1 = 17

4.

                    0a  //tag  10表示这是一个CONSTANT_Methodref_info结构
                    00 04 //class_index 指向常量池中第4个常量所表示的类
                    00 0e  //name_and_type_index 指向常量池中第14个常量所表示的方法

 5. 09 00 03 00 0F

                        09 //tag
                        00 03 //指向常量池中第3个常量所表示的类
                        00 0f //指向常量池中第15个常量所表示的变量

 6. 07 00 10

指向的是常量池中第16个常量所表示的class名称

7. 07 00 11

同上

8. 01 00 04 74 65 73 74

                        01 //tag  1表示这是一个CONSTANT_Utf8结构
                        00 04 //表示这个字符串的长度是4字节,也就是后面的四个字节74 65 73 74
                        74 65 73 74 //通过ASCII码表转换后,表示的是字符串“test”

完整的常量池

          00 12  常量池的数目 18-1=17
          0a 00 04 00 0e  方法:java.lang.Ojbect void ()
          09 00 03 00 0f   方法 :Hello int test() 
          07 00 10  字符串:Hello
          07 00 11 字符串:java.lang.Ojbect
          01 00 04 74 65 73 74 字符串:test
          01 00 01 49  字符串:I
          01 00 06 3c 69 6e 69 74 3e 字符串:
          01 00 03 28 29 56 字符串:()V
          01 00 04 43 6f 64 65 字符串:Code 
          01 00 0f 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65 字符串:LineNumberTable 
          01 00 03 28 29 49 字符串:()I
          01 00 0a 53 6f 75 72 63 65 46 69 6c 65 字符串:SourceFile
          01 00 0a 48 65 6c 6c 6f 2e 6a 61 76 61 字符串:Hello.java
          0c 00 07 00 08 NameAndType: ()V
          0c 00 05 00 06 NameAndType:test I
          01 00 05 48 65 6c 6c 6f 字符串:Hello
          01 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 字符串: java/lang/Object
public class org.jvminternals.SimpleClass
  SourceFile: "SimpleClass.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#17         //  java/lang/Object."":()V
   #2 = Fieldref           #18.#19        //  java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #20            //  "Hello"
   #4 = Methodref          #21.#22        //  java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #23            //  org/jvminternals/SimpleClass
   #6 = Class              #24            //  java/lang/Object
   #7 = Utf8               
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lorg/jvminternals/SimpleClass;
  #14 = Utf8               sayHello
  #15 = Utf8               SourceFile
  #16 = Utf8               SimpleClass.java
  #17 = NameAndType        #7:#8          //  "":()V
  #18 = Class              #25            //  java/lang/System
  #19 = NameAndType        #26:#27        //  out:Ljava/io/PrintStream;
  #20 = Utf8               Hello
  #21 = Class              #28            //  java/io/PrintStream
  #22 = NameAndType        #29:#30        //  println:(Ljava/lang/String;)V
  #23 = Utf8               org/jvminternals/SimpleClass
  #24 = Utf8               java/lang/Object
  #25 = Utf8               java/lang/System
  #26 = Utf8               out
  #27 = Utf8               Ljava/io/PrintStream;
  #28 = Utf8               java/io/PrintStream
  #29 = Utf8               println
  #30 = Utf8               (Ljava/lang/String;)V
{
  public org.jvminternals.SimpleClass();
    Signature: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
        0: aload_0
        1: invokespecial #1    // Method java/lang/Object."":()V
        4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
          0      5      0    this   Lorg/jvminternals/SimpleClass;

  public void sayHello();
    Signature: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
        0: getstatic      #2    // Field java/lang/System.out:Ljava/io/PrintStream;
        3: ldc            #3    // String "Hello"
        5: invokevirtual  #4    // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        8: return
      LineNumberTable:
        line 6: 0
        line 7: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
          0      9      0    this   Lorg/jvminternals/SimpleClass;
}

9 00 21

表示的是这个变量的访问位置位

 10. 00 03

这个表示的是this_class指向的是constant pool的索引值,此处为3表示的就是指向常量池的第三项,即“HELLO”.

11.00 04:super class

同上,表示的是第四个常量,指的是“java/lang/object”.

12. 00 00:interfaces

包含的是interfaces_count和interfaces[]两个字段,此处无接口故不存在相关的阿选项

13. 00 01 00 01 00 05 00 06 00 00:fields

               00 01 fields count        //表示成员变量的个数,此处为1个
               00 02 00 05 00 06 00 00   //成员变量的结构

每个成员的变量对应一个field_info结构

               field_info {
                         u2 access_flags; 0002 // ACC_PRIVATE
                         u2 name_index; 0005 // "test"
                         u2 descriptor_index; 0006 // "I"
                         u2 attributes_count; 0000 // "private int test"
                         attribute_info attributes[attributes_count]; // 没有附加属性
               }

14。 00 02 00 01 00 07 00 08 00 01 00 09_______:methods

00 02:method_count(之所以会有两个方法,主要原因是JVM会自动挡阿生成一个方法)

接着是两个method_info结构:

                    method_info {
                         u2 access_flags;
                         u2 name_index;
                         u2 descriptor_index;
                         u2 attributes_count;
                         attribute_info attributes[attributes_count];
                    }

前三个字段与field相同,分析得第一个方法是"public void "

attribute_name_index为00 09,指向的是第九个常量,即code

                         00 01 ACC_PUBLIC
                         00 07  
                         00 08  V()

code attribute的作用是保存该方法的结构所对应的字节码

attribute_length表示attribute所包含的字节数,这里为0000001d,即是39个字节,不包含attribute_name_index和attribute_length字段。

     Code_attribute {
          u2 attribute_name_index;
          u4 attribute_length;
          u2 max_stack;
          u2 max_locals;
          u4 code_length;
          u1 code[code_length];
          u2 exception_table_length;
          { 
               u2 start_pc;
               u2 end_pc;
               u2 handler_pc;
               u2 catch_type;
          } exception_table[exception_table_length];
          u2 attributes_count;
          attribute_info attributes[attributes_count];
     }

max_stack表示这个方法运行的任何时刻所能达到的操作数栈的最大深度,这里是0001
max_locals表示方法执行期间创建的局部变量的数目,包含用来表示传入的参数的局部变量,这里是0001.
接下来的code_length表示该方法的所包含的字节码的字节数以及具体的指令码。
这里的字节码长度为00000005,即是后面的5个字节 2a b7 00 01 b1为对应的字节码指令的指令码。

15. attributes

最后剩下的内容是attributes,表示的是整个class文件的附加属性。结构类似attribute

          SourceFile_attribute {
               u2 attribute_name_index; // source
               u4 attribute_length; // 2
               u2 sourcefile_index; // hello。java
          }

最后一个主要表明的是当前的class文件是由Hello.java文件编译而来的。

这一部分关于字节码的理解可以参考从字节码层面看“HelloWorld” - liuxiaopeng - 博客园 (cnblogs.com)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/945328.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号