日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

JVM003_属性表

發布時間:2025/3/12 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM003_属性表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

屬性表

預備知識

  • javac -g Xxx.java 在生成class文件的時候生成所有調試信息
  • javap -v Xxx.class 輸出附加信息

屬性表結構

類型名稱數量備注
u2attribute_name_index1屬性名稱索引,指向一個CONSTANT_Utf8_info型常量的索引
u4attribute_length1該屬性表的長度
u1infoattribute_length屬性值

Code屬性表

Code屬性表結構釋義

  • attribute_name_index是一項指向CONSTANT_Utf8_info型常量的索引,對應的值固定為‘Code’,代表了該屬性的屬性名稱。

  • attribute_length代表了屬性值的長度。屬性值的長度=屬性表總長度-6個字節。

  • max_stack代表操作數棧深度的最大值。虛擬機運行時根據該值來分配棧幀中操作數棧的深度。

  • max_locals 代表了局部變量表所需的存儲空間。其計算單位為‘變量槽’。變量槽是JVM為局部變量表分配內存所使用的最小單位。對于byte、char、float、int、short、boolean及returnAddress等長度不超過32位的數據類型,每個局部變量占用1個變量槽,double及long這兩種64位的數據類型,占用兩個變量槽。

    • 局部變量表中的變量槽會被復用,所以變量槽的個數不一定等于參數個數。當代碼執行 超過一個變量的作用域時,其原型占用的變量槽將會被復用。
    • 操作數棧及局部變量表直接決定了該方法的棧幀所耗費的內存。
  • code_length代表Java源程序編譯后生成的字節碼指令個數,由于一個字節碼占用1字節,所以也就是字節碼的長度。

    • 理論值為2^32,實際最大值為65535。
  • code 用于存儲編譯生產的一些列字節碼指令。

  • exception_info 該方法的顯示異常處理表集合,非必須。

    • 顯示異常處理表結構

      類型名稱數量
      u2start_pc1
      u2end_pc1
      u2handler_pc1
      u2catch_type1

      上表表示當字節碼從[start_pc,end_pc)行出現了類型為catch_type或其子類的異常,那么就轉至handler_pc行進行處理。當catch_type為0時,代表任意異常都需要跳轉到handler_pc行處理。

      -注意 : 此處的行指的是字節碼相對于方法體開始的偏移量。

Code屬性表實例

public class Test{private static final int size = 100;public void sout(){System.out.println(size);}public int toDouble(int prame){return 2*prame;}public int add(int p1,int p2){return p1+p2;}public static int toTriple(int prame){return 3*prame;} }

將代碼編譯 javac -g Test.java,在反編譯javap -v Test.class

Classfile /D:/notes/JVM/code/Test.classLast modified 2021-3-29; size 746 bytesMD5 checksum a1a23cf998350d444d9438782f3af659Compiled from "Test.java" public class Testminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER Constant pool:#1 = Methodref #5.#28 // java/lang/Object."<init>":()V#2 = Fieldref #29.#30 // java/lang/System.out:Ljava/io/PrintStream;#3 = Class #31 // Test#4 = Methodref #32.#33 // java/io/PrintStream.println:(I)V#5 = Class #34 // java/lang/Object#6 = Utf8 size#7 = Utf8 I#8 = Utf8 ConstantValue#9 = Integer 100#10 = Utf8 <init>#11 = Utf8 ()V#12 = Utf8 Code#13 = Utf8 LineNumberTable#14 = Utf8 LocalVariableTable#15 = Utf8 this#16 = Utf8 LTest;#17 = Utf8 sout#18 = Utf8 toDouble#19 = Utf8 (I)I#20 = Utf8 prame#21 = Utf8 add#22 = Utf8 (II)I#23 = Utf8 p1#24 = Utf8 p2#25 = Utf8 toTriple#26 = Utf8 SourceFile#27 = Utf8 Test.java#28 = NameAndType #10:#11 // "<init>":()V#29 = Class #35 // java/lang/System#30 = NameAndType #36:#37 // out:Ljava/io/PrintStream;#31 = Utf8 Test#32 = Class #38 // java/io/PrintStream#33 = NameAndType #39:#40 // println:(I)V#34 = Utf8 java/lang/Object#35 = Utf8 java/lang/System#36 = Utf8 out#37 = Utf8 Ljava/io/PrintStream;#38 = Utf8 java/io/PrintStream#39 = Utf8 println#40 = Utf8 (I)V {public Test();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 1: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 this LTest; // 疑問:為什么這里的Length為5?public void sout();descriptor: ()Vflags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;3: bipush 1005: invokevirtual #4 // Method java/io/PrintStream.println:(I)V8: returnLineNumberTable:line 5: 0line 6: 8LocalVariableTable:Start Length Slot Name Signature0 9 0 this LTest;public int toDouble(int);descriptor: (I)Iflags: ACC_PUBLICCode:stack=2, locals=2, args_size=20: iconst_21: iload_12: imul3: ireturnLineNumberTable:line 9: 0LocalVariableTable:Start Length Slot Name Signature0 4 0 this LTest;0 4 1 prame Ipublic int add(int, int);descriptor: (II)Iflags: ACC_PUBLICCode:stack=2, locals=3, args_size=30: iload_11: iload_22: iadd3: ireturnLineNumberTable:line 13: 0LocalVariableTable:Start Length Slot Name Signature0 4 0 this LTest;0 4 1 p1 I0 4 2 p2 Ipublic static int toTriple(int);descriptor: (I)Iflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=1, args_size=10: iconst_31: iload_02: imul3: ireturnLineNumberTable:line 17: 0LocalVariableTable:Start Length Slot Name Signature0 4 0 prame I }

現在對toDouble方法進行分析

Code屬性下

  • stack=2表示操作數棧的最大深度為2
  • locals=2表示本地變量表的存儲空間為2個變量槽
  • args_size=2表示方法的傳參有2個
    • 這里有個問題,明明方法簽名為toDouble(int prame),只有一個參數,為什么這里顯示有兩個參數呢?因為在編譯的時候,會自動的傳入一個參數this。并放到局部變量表的0號槽中。
  • LocalVariableTable 表示各變量在局部變量表中的存儲情況。
Code:stack=2, locals=2, args_size=20: iconst_2 # 將int型數值2推送到操作數棧頂1: iload_1 # 將第二個int型本地變量推動至棧頂,即將局部變量表中solt索引為1的變量推送至操作數棧棧頂2: imul # 將棧頂兩個int類型數值相乘并將結果壓入棧頂3: ireturn # 從方法中返回int類型的數據,即將操作數棧棧頂元素彈出

Exceptions屬性

Exceptions屬性是在方法表中與Code屬性平級的一項屬性,與Code屬性中的異常表不是同一東西,列舉出方法中可能拋出的受查異常(Checked Excepitons) , 也就是方法描述時在throws關鍵字后面列舉的異常。

Exceptions屬性結構

類型名稱數量備注
u2attribute_name_index1屬性名索引
u4attribute_length1屬性長度
u2number_of_exceptions1拋出的受查異常種數
u2exception_index_tablenubmer_of_exceptions指向常量池中CONSTANT_class_info型常量的索引

LineNumberTable屬性

用來描述Java源碼與字節碼行號之間的對應關系。這里的字節碼行號指的是字節碼距方法體開始的偏移量。是一個非必須屬性。默認生成。可使用-g: none或-g:lines來選擇或者取消。

若不生成改屬性,那么在拋出異常的時候,堆棧中將不會顯示出錯的行號,在調試時無法按照源碼行來設置斷點。

LineNumberTable屬性結構

類型名稱數量備注
u2attribute_name_index1屬性名索引
u4attribute_length1屬性長度
u2line_number_table_length1屬性個數
line_number_infoline_number_tableline_number_table_lengthline_number_info集合

line_number_info

類型名稱備注
u2start_pc字節碼行號
u2line_numberJava源碼行號

LocalVariableTable

用來描述棧幀中局部變量表的變量與Java源碼中定義的變量之間的關系,是非必須的。-g:none,-g: vars來取消或選擇。默認會生成到class文件中,若取消該屬性,那么當他人引用時,所有的參數名稱都會消失。

LocalVariableTable屬性結構

類型名稱數量備注
u2attribute_name_index1屬性名索引
u4attribute_length1屬性長度
u2local_variable_table_length1本地變量表長度
local_variable_infolocal_variable_tablelocal_variable_table_length本地變量表

local_variable_info結構

類型名稱數量備注
u2start_pc1該局部變量的聲明周期的開始字節碼偏移量
u2length1該局部變量的作用范圍
u2name_index1是指向CONSTANT_Utf8_info型常量的索引,代表局部變量的名稱
u2descriptor_index1是指向CONSTANT_Utf8_info型常量的索引,代表局部變量的描述符
u2index1在局部變量表中的變量槽位置

在JDK引入泛型后增加了**LocalVariableTypeTable **屬性,僅僅是將descriptor_index替換為字段的特征簽名(Signature) 。

SourceFile及SourceDebugExtension屬性

SourceFile屬性用于記錄生成這個Class文件的源碼文件名稱。 可選;-g:none,-g: source來關閉或開啟。若不生成,在拋出異常的時候,堆棧中不會顯示出錯代碼所屬的文件名。

SouceFile屬性結構

類型名稱數量備注
u2attribute_name_index1屬性名索引
u4attribute_length1屬性長度
u2sourcefile_index1指向常量池中CONSTANT_Utf8_info型常量的索引, 常量值是源碼文件的文件名

JDK 5時, 新增了SourceDebugExtension屬性用于存儲額外的代碼調試信息。

類型名稱數量備注
u2attribute_name_index1屬性名索引
u4attribute_length1屬性長度
u1debug_extension[attribute_length]1額外的調試信息

ConstantValue屬性

該屬性的作用是通知虛擬機自動為靜態變量賦值。只有被static修飾的變量才能使用這項屬性。

非靜態變量實例構造器()方法中賦值
靜態變量類構造器()方法中賦值
靜態變量使用ConstantValue屬性

Oracle公司的選擇是,常量(static final共同修飾的變量)且其類型為基礎類型或String,使用ConstantValue屬性來進行初始化,非基礎類型及字符串,或僅被static修飾那么在()中進行初始化。

ConstantValue屬性結構

類型名稱數量備注
u2attribute_name_index1屬性名索引
u4attribute_length1屬性長度
u2constantvalue_index1常量池中一個字面量的引用

總結

以上是生活随笔為你收集整理的JVM003_属性表的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。