文章目錄
- 前言
- 一、方法表結構
- 二、方法計數器
- 三、方法表資料解析 ( init 構造方法 )
-
- 1、方法通路标志
- 2、方法名稱索引
- 3、方法傳回類型
- 4、方法屬性數量
前言
上一篇部落格 【Java 虛拟機原理】Class 位元組碼二進制檔案分析 四 ( 字段表資料結構 | 字段表詳細分析 | 通路标志 | 字段名稱 | 字段描述符 | 屬性項目 ) 分析了字段表的一些資料 ;
目前的位元組碼檔案中隻有
1
1
1 個字段 , 字段表顯示
1
1
1 個字段結束後 , 後面的位元組是 方法計數器 和 方法表 的資料 ;
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLi0zaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLwIzX39GZhh2csATMflHLwEzX4xSZz91ZsAzMfRHLGZkRGZkRfJ3bs92YskmNhVTYykVNQJVMRhXVEF1X0hXZ0xiNx8VZ6l2cssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL5kTM3MmN5QmMhFGNzQGZxYzXwMTM0UTMxEzLcFDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
本篇部落格中 , 繼續向後分析 位元組碼對應資料 ;
分析的原始資料是 【Java 虛拟機原理】Class 位元組碼二進制檔案分析 一 ( 位元組碼檔案附加資訊 | 魔數 | 次版本号 | 主版本号 | 常量池個數 ) 二、位元組碼檔案示例 章節中的 Java 源碼 , Class 位元組碼 , 位元組碼附加資訊 ;
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
位元組碼附加資訊 :
D:\jvm>javap -v Student.class
Classfile /D:/jvm/Student.class
Last modified 2021-9-4; size 392 bytes
MD5 checksum 8b9bb897bb8cf2a8addf04be5b7b915f
Compiled from "Student.java"
public class Student
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #4.#17 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#18 // Student.name:Ljava/lang/String;
#3 = Class #19 // Student
#4 = Class #20 // java/lang/Object
#5 = Utf8 name
#6 = Utf8 Ljava/lang/String;
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 getName
#12 = Utf8 ()Ljava/lang/String;
#13 = Utf8 setName
#14 = Utf8 (Ljava/lang/String;)V
#15 = Utf8 SourceFile
#16 = Utf8 Student.java
#17 = NameAndType #7:#8 // "<init>":()V
#18 = NameAndType #5:#6 // name:Ljava/lang/String;
#19 = Utf8 Student
#20 = Utf8 java/lang/Object
{
public Student();
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 1: 0
public java.lang.String getName();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field name:Ljava/lang/String;
4: areturn
LineNumberTable:
line 5: 0
public void setName(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: putfield #2 // Field name:Ljava/lang/String;
5: return
LineNumberTable:
line 9: 0
line 10: 5
}
SourceFile: "Student.java"
一、方法表結構
字段表之後的
2
2
2 位元組就是方法計數器 , 記錄目前位元組碼有多少個方法 ;
方法計數器 後 就是方法表 , 方發表中每個方法都是 一個 method_info 資料結構 ;
假如 方法計數器 中 方法個數是
3
3
3 , 那麼方法表中有
3
3
3 個 method_info ;
方法表 method_info 結構 : 方發表結構 與 字段表結構一樣 ;
方發表就是若幹上述 method_info 結構的排列 , 方法表的方法排列完畢後 , 是屬性計數器 和 屬性表 ;
二、方法計數器
方法計數器的值為
00 03
, 說明有
3
3
3 個方法 ;
三、方法表資料解析 ( init 構造方法 )
這是位元組碼 附加資訊 中的構造方法資料 :
public Student();
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 1: 0
1、方法通路标志
access_flag ( 方法通路權限 ) : 方法計數器 後 的
2
2
2 位元組 , 是 方發表中 第一個 method_info 方法資訊的 方法通路标志 ;
00 01
表示該方法是 public 的 ;
方法通路标志 :
2、方法名稱索引
name_index ( 方法名稱索引 ) :
2
2
2 位元組 ,
00 07
表示常量表中的
#7
, 常量為 :
Constant pool:
#7 = Utf8 <init>
<init>
方法指的是構造方法 ;
3、方法傳回類型
descriptor_index ( 方法傳回類型 ) :
2
2
2 位元組 ,
00 08
表示常量表中的
#8
, 常量為 :
Constant pool:
#8 = Utf8 ()V
()V
方法的傳回類型是 void , 沒有傳回類型 ;
4、方法屬性數量
attributes_count ( 方法屬性數量 ) :
2
2
2 位元組 ,
00 01
表示方法屬性數量
1
1
1 個