详解 JVM 字节码(5)

作者: zidea | 来源:发表于2019-05-03 18:13 被阅读10次
jvm

今天进入最关键也是最重要部分方法表,也是有一定难度。

定义方法访问标记
00 01 :表示一个 public 方法,这是一个构造方法。
00 0B : 对应常量池 # 11 <init>
00 0C : 对应常量池 #12 ()V
00 01 : 说明这个方法本身只有一个属性,每一个方法表都有 code 属性保存这个方法的结构
00 0D : #13 = Utf8 Code
00 00 00 43 (67): 字节长度


code 信息

00 02 :max_stack
00 01 : max_local
00 00 00 11: (17)code_length 表示该方法所包含字节码的字节数以及具体的指令码
我们可以根据 code_length 向后数 17 字节,这是函数 code 执行指令
2A B7 00 01 2A 12 02 B5 00 03 2A 10 0A B5 00 04 B1


code 信息

此图与上面字节码相对应。图中出现的为助记符,助记符和16进制对应

  • 2A (aload_0)
    可以通过在 jclasslib 面板点击助记符aload_o跳转到 JVM 官方 JVM 规范的中助记符对应章节。

    aload 助记符
    n 表示索引,是局部变量数组的索引,在此位置(n)会包含一个引用,而且将该局部变量推到栈顶
  • B7 (invokespecial)


    invokespecial 助记符

    表示调用父类的构造方法,而且还有参数为其后面的两个字节,
    00 01 :#1 = Methodref #6.#28 // java/lang/Object."<init>":()V
    表示父类的构造方法调用 Object 的 init 方法

  • 0A

  • 12(ldc)


    ldc 助记符

    从常量池获取元素

  • 02 #2 = String #29 // basic

  • B5 (putfiled)


    putfield

    为对象设置属性,属性为
    00 03 #3 = Fieldref #5.#30 // com/zidea/Tut.title:Ljava/lang/String;
    上面是从常量池读取 basic 字面量赋值给对象属性 title。

  • 10(bipush)


    bipush

    具体赋值为其后字节 0A(10)
    将 10 放置到栈顶然后准备给 courses 属性进行赋值,内容重复大家可以自己感受一下

  • B1(return)


    return

    表示方法执行完毕,返回为 void。

随后两个字节使用表示异常表信息的数量,如果为 0 表示没有异常信息表

00 00

表示异常表信息,异常表数量为 0 没有异常信息。

00 02

表示存在两个属性,随后

00 0E

这里的 00 0E(14) #14 = Utf8 LineNumberTable 对应常量池内容,LineNumberTable 用途是将字节码和实际代码行号进行对应便于调试查找问题

00 00 00 0E
00 03 00 00 00 03 00 04 00 04 00 0A 00 05

00 03 表示有三个对应关系

  • 00 00 00 03 :0 对应 3

  • 00 04 00 04

  • 00 0A 00 05 :10 对应 5 行代码


    LineNumberTable

    [图片上传失败...(image-950363-1556845759146)]

  • 00 0F (15) #15 = Utf8 LocalVariableTable
    表示第二个属性名字为 15 对应表示局部变量表
    00 00 00 0C 表示连续 12 字节表示局部变量

00 01 00 00 00 11 00 10 00 11 00 00
  • 00 01 表示构造方法里局部变量的个数

  • 00 00 和 00 11 表示局部变量开始和结束的位置

  • 00 10 (16)表示局部变量在常量池位置 #16 = Utf8 this

  • 00 11 (17)对局部变量的描述 #17 = Utf8 Lcom/zidea/Tut;

  • 00 00 可以跳过去
    我们知道 java 中每一个方法都是访问到 this 其实在 JVM 编译时,this 是作为第一个参数传入到方法才能被使用。
    我们第一个构造方法的字节码分析到此就结束,可以开始下一个方法也就是 getTitle,相同内容我就不多赘述了,大家可以自动手查一查。

  • 00 01 (access_flag) ACC_PUBLIC)
    00 12 : #18 = Utf8 getTitle(方法名)
    00 13 : #19 = Utf8 ()Ljava/lang/String;(描述符)
    00 01 :表示方法属性
    00 0D :对应 code
    00 00 00 2F(47)字节表示 code 的信息
    00 01 :
    00 01 :局部变量表为 this。
    00 00 00 05 :表示该方法字节码所占长度,可以向后数 5 个字节。

  • 2A aload_0

  • B4 (getfield) 从成员变量获取值 参数为 00 03 表示指向常量池 3 元素 #3 = Fieldref #5.#30 // com/zidea/Tut.title:Ljava/lang/String;

  • B0(Return reference from method)表示返回一个引用,因为字符串 ”basic“ 是一个引用对象所以这里返回字符串的引用。

  • 00 00 :表示没有异常表

  • 00 02 :表示两个属性

  • 00 0E : 第一个属性为 LineNumberTable
    回顾一下 LineNumberTable 的属性有哪些

  • attribute_name_index u2

  • attribute_length u4

  • line_number_table_length

    • start_pc
    • line_number
  • 00 00 00 06 (属性长度为 6 )

00 01 00 00 00 08

表示偏移量为 0 对应行号 8 ,行号 8 内容为return title;

  • 00 0F 局部变量表
  • 00 00 00 0C 表示局部变量的长度 12 数 12 字节
00 01 00 00 00 05 00 10 00 11 00 00

表示有一个局部变量 this 。

  • 00 00
    这样就结束了getTitle方法,我们可以开始第三个方法public void setTitle(String title)
  • 00 01 pubic
  • 00 14 : #20 = Utf8 setTitle
  • 00 15 : (Ljava/lang/String;)V 返回值为 void 接收一个 String 对象作为参数
  • 00 01 : 方法的属性
  • 00 0D : 方法属性为 Code
  • 00 00 00 3E : 62 字节代表 code 对应字节码
  • 00 02 : 最大操作栈数
  • 00 02 :局部变量个数
  • 00 00 00 06:方法执行字节码
2A 2B B5 00 03 B1
  • 2A(aload_0)

  • 2B(aloda_1)

  • B5(putfield) 参数 03 赋值给 title

  • B1(return)

  • 00 00

  • 00 02

  • 00 0E 行号表

  • 00 00 00 0A 向后数 10 个字节

00 02 00 00 00 0C 00 05 00 0D

有两个对应关系

  • 00 0F :局部变量表
  • 00 00 00 16:表示有 22 个字节表示局部变量表的信息
  • 00 02 表示有两个局部变量
00 01 00 1A 00 00 00 02 00 1B

随后字节码可以按上面规则进行分析。

相关文章

  • JVM

    JVM 基础-类字节码详解 多语言编译为字节码在 JVM 运行 Java 字节码文件-- Class文件的结构属性...

  • 详解 JVM 字节码(5)

    今天进入最关键也是最重要部分方法表,也是有一定难度。 定义方法访问标记00 01 :表示一个 public 方法,...

  • JVM知识精粹

    1.jvm执行字节码文件 流程:jvm通过类加载器加载字节码文件----字节码校验器---翻译字节码(解释执行,反...

  • Java并发机制的底层原理

    Java程序执行:Java代码→Java字节码→字节码被类加载器加载到JVM里,JVM执行字节码→转化为汇编指令在...

  • Java并发机制的底层实现原理

        Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为...

  • 详解 JVM 字节码 (1)

    在开始分析 class 字节码前我们先补一补一些基础知识,帮助我们更好地了解 jvm 是如何执行字节码的。大家可能...

  • 详解 JVM 字节码(3)

    版本信息 上一次我们分析前 4 个字节为魔数,继续向下数 4 字节为版本号信息(前两个字节表示此版本号,后两个字节...

  • 详解 JVM 字节码(2)

    什么是字节码,为什么需要字节码编译 JVM 编译成机器码, 我们看一看 Java 编译过程 java 源码 编译为...

  • 详解 JVM 字节码(Four)

    访问标志 访问标志信息包括该 Class 文件是类还是接口,是否被定义成 public,是否是 abstract,...

  • 详解 JVM 字节码(8)

    字节码的执行方式,程序执行有两种是编译执行和解释执行,JIT 编译产生本地代码生成机器码来执行。现在的 JVM 解...

网友评论

    本文标题:详解 JVM 字节码(5)

    本文链接:https://www.haomeiwen.com/subject/pchanqtx.html