您好,登錄后才能下訂單哦!
小編給大家分享一下JVM中Java字節碼文件的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
每一個class字節碼文件都唯一對應一個類或接口,class文件中記錄中類或接口的基本信息,但反之不成立,不是每一個類或接口都有一個唯一對應的字節碼文件,首先類或接口的字節碼可以不以文件的方式存儲,可以直接從內存中生成字節碼,而不產生.class文件,動態代理的原理就是直接內存中生成字節碼流,根據加載字節碼流進行類加載操作,類實例化,生成代理對象。
字節碼文件記錄的信息:魔術,class文件主次版本,常量池數量及常量池表,類或接口的訪問標志,類索引,超類索引,接口數量及接口表,字段數量及字段表,方法數量及方法表,sjz.java.tedu.cn屬性屬性及屬性表,jvm中使用類c結構體表示每一種屬性,結構體中類型種類有兩種,無符號數及表,以 _info結尾表示表,以 u1,u2,u4,u8分別表示1字節,2字節,4字節,8字節無符號數
ClassFile{
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count];
u2 acc_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
魔術:四個字節,用于定義此字節碼文件是否符合虛擬機規范,保證字節碼文件不會威脅虛擬機的安全,若為cafebabe則表示字節碼符合虛擬機規范
主次版本號:四個字節,前兩字節表示次版本號,后兩字節表示主版本號,用于定義編譯的字節碼文件格式版本,低版本虛擬機拒絕運行高版本字節碼文件,但高版本虛擬機會向下兼容低版本字節碼文件
常量池數量及常量池表:這部分主要統計類或接口的字面量和符號引用,用于每個類或接口擁有的字面量和符號引用屬性不一定相同,所有需要兩個字節的長度來表示常量池數目,常量池數目計數從1開始,比如類或接口中總共有兩個字面量符號引用,則常量池數目為2,注意,不是從0開始計數,0可能另有用處,可以用來表示類或接口中未出現的引用,用來表示超級父類java.long.Object全限定名的索引,常量池表是一個數組,一共有18種類型,每一種類型有一個tag屬性與之對應,constant_utf8_info用于表示文本字符串,類和接口全限定名,字段名稱及描述符,方法名稱及描述符等常量信息,constant_integer_info用于存儲int類型的常量信息,只存儲int類型的值,不存儲其他符合引用信息,比如 final int a=1 符號引用信息為a,值為1,constant_float_info用于存儲float類型常量信息,也是只存儲float值,不存儲引用信息,constant_long_info用于存儲long類型的常量信息,constant_double_info用于存儲double類型的常量信息,constant_class_info用于存儲指向常量池列表constant_unf8_info類和接口全限定名的有效引用,constant_string_info用于存儲指定常量池列表constant_utf8_info某常量項的有效索引,指向文本字符串,constant_fieldref_info用于存儲指向常量池列表constant_class_info常量項和constant_nameandtype_info常量項的有效索引,constant_methodref_info用于存儲指向常量池列表constant_class_info常量項和constant_nameandtype_info常量項的有效索引,constant_interfacemethodref_info用于存儲指向常量池列表constant_class_info常量項和constant_nameandtype_info常量項的有效索引,constant_nameandtype_info用于存儲指向常量池列表constant_utf8_info常量項的有效索引,可以通過所有找到對應類及描述符,constant_methodtype_info用于存儲指向常量池constant_utf8_info常量項,表示方法類型,找到對應的方法描述符,constant_methodhandle_info用于表示方法句柄,屬性reference_kind表示方法句柄的類型,1-4表示為字段創建的方法句柄,5-8表示為類方法(構造、實例、靜態)創建的句柄,9表示為接口方法創建的句柄,reference_index屬性指向根據reference_kind對應的常量池列表,constant_invokedynamic_info用于存儲當前字節碼文件中引導方法bootstrap_method數組的有效索引和指向常量池constant_nameandtype_info常量項的有效索引
constant_utf8_info{
u1 tag;
u2 length;
u1 bytes[length];
}
constant_integer_info{
u1 tag;
u4 bytes;
}
constant_float_info{
u1 tag;
u4 float;
}
constant_long_info{
u1 falg;
u8 long;
}
constant_double_info{
u1 tag;
u4 double;
}
constant_class_info{
u1 tag;
u2 name_index;
}
constant_string_info{
u1 tag;
u2 string_index;
}
constant_fieldref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
constant_mathodref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
constant_interfacemathodref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
constant_nameandtype_info{
u1 tag;
u2 class_index;
u2 descriptor_index;
}
constant_methodhandle_info{
u1 tag;
u2 reference_kind;
u2 reference_index;
}
constant_methodtype_info{
u1 tag;
u2 descriptor_index;
}
constant_invokedynamic_info{
u1 tag;
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
}
訪問標志:兩個字節,用于定義字節碼文件所表示的類或接口的訪問權限,如判斷是類還是接口,類是否被abstract修飾,類是否被final修飾, acc_interface表示是接口,acc_annotation表示是注解類型,acc_enum表示是枚舉類型,acc_public 表示類或接口是public訪問權限,acc_final表示類不允許被繼承,acc_abstract表示類為抽象類,acc_super表示類調用實例方法時需進行特殊操作
類索引及父類索引:四個字節,用于存儲指向常量池constant_class_info對應的有效索引,而constant_class_info存儲常量池列表的constant_utf8_info常量項索引,根據此索引可找到類和父類的全限定名
接口數量及接口表:接口屬性用于存儲當前類或接口的直接超類接口數量,接口表是一個數組,記住,只有常量池表從1開始計數,其余都是從數組下表0開始計數,接口表數組的每一個數組元素存儲此類或接口的直接超類接口的有效索引,根據此索引找到constant_class_info對應的常量項,根據constant_class_info可找到對應直接超類接口的全限定名
字段數量及字段表:字段數量用于存儲類或接口的字段數目,包括類字段和實例字段,字段表為一個數組,每一個數組元素都相當于一個field_info結構的對象,field_info結構包含字段完整信息:字段標識符,字段訪問修飾符,字段是類字段還是實例字段,字段是否為常量等,注意:此處字段表示當前類或接口的字段,不包括從超類或接口繼承的字段,java語法規范不允許同一個類或接口中出現同一字段名的不同字段,但是class文件中卻可以允許出現相同字段名的不同字段,只有字段的描述符不同即可,field_info結構屬性:access_flags用于存儲字段的訪問標志,acc_private,acc_protected,acc_public,acc_final,acc_static,acc_volatile等,注意:acc_final與acc_volatile不能同時出現在同一字段,name_index指向常量池constant_utf8_info常量項的有效索引,獲取當前字段的簡單名稱,descriptor_index指向常量池constant_utf8_info常量項的有效索引,獲取當前字段的描述符,attribute_count,attributes[attributes_count]這兩項表示字段的屬性信息,用于描述字段相關信息,attribute數組每一個元素都是一個attribute_info結構的元素
field_info{
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attribuyes_count];
}
方法數量及方法表:方法數量用于存儲當前類或接口的方法數目,包括實例方法,類方法,抽象方法,方法表是一個數組,每一個數組元素都是一個method_info結構,method_info結構包含方法的完整信息:方法描述符,訪問修飾符,是否為final方法,是否為abstract方法等,注意:此處的方法數組只是表示當前類或接口的所有方法,并不包括從超類及父接口繼承來的方法,java語法規范java類或接口中不允許出現方法簽名完全一樣的方法同時出現,會編譯報錯,而字節碼層面卻允許方法簽名完全相同的方法同時出現,只需要保證方法的返回值類型不同,method_info結構屬性與field_info一致,但acc_flags類型不盡相同,注意acc_abstract不能與acc_final,acc_static,acc_private,acc_synchronized,acc_native同時使用,接口方法中只能使用acc_public,acc_abstract,此處我有一個疑問,接口中default方法有沒有對應的訪問標志,注意:方法只能使用acc_private,acc_protected,acc_public訪問標志
method_info{
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attribuyes_count];
}
屬性數量及屬性表:屬性數量表示當前字節碼文件中attribute_info表數目,屬性表是一個數組,每一個數組元素都是attribute_info結構,attribute_info結構表示屬性的完整信息:第一項指向常量池constant_utf8_info某常量項的有效索引,根據此索引可找到屬性對應名稱,屬性可以出現在classFile,字段表,方法表中,用以描述相關信息,attribute_info結構完整信息:attribute_name_index指向常量池constant_utf8_info常量項的有效索引,獲取屬性名稱,attribute_length用于指明info數組長度,info[attribute_length]用于存儲屬性的數據信息,必須實現的數據信息:Code,ConstantValue,Exceptions, code屬性用于描述method_info的具體相關信息,attribute_name_index指向常量池constant_utf8_info常量項的有效索引,獲取屬性名稱,即code,attribute_length表示attribute表示attribute_info長度,不包括attribute_name_index和attribute_length的初始6字節,max_stack描述當前方法最大棧深度,max_locals描述當前方法的局部變量表,code_length表示code數組長度,code[]表示當前方法編譯后的字節碼, ContantVaue位于field_info結構中,用于通知虛擬機對類變量進行初始化,即字段需要被acc_static修飾,當前類常量不需要ContantValue通知虛擬機執行初始化,早就執行好了,實例字段此時不需要初始化
attribute_info{
u2 attribute_name_index;
u4 attribute_length;
u1 info[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;
exception_info exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
constantvalue_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 constantvalue_index;
}
簡單名稱與描述符:
簡單名稱是指字段或方法的簡單的一種描述,比如person class:private String name字段簡單名稱為name,Object class:public String toString()方法簡單名稱為toString,注意:字段或方法簡單名稱不允許出現 . : / [ 等ASSIC或Unicode字符表示形式
描述符一般指字段或方法的類型,字段描述符表示字段類型描述,方法描述符表示參數描述與返回值描述,如:person class:private String name字段描述符為Ljava.lang.String,com.test.Person class:setName(String name)方法描述符為(Ljava.lang.String)V,注意:其中V表示返回值為void類型,如果參數為void則表示為()Ljava.lang.Object,表示無參的返回值為java.lang.Object引用類型的方法描述符
字段描述符解釋:B byte 字節類型,Z boolean 布爾類型,C char 字符類型,S short 短整型,I 整型,L long 長整型,F float 單進度浮點類型,D double 雙精度浮點類型,L reference 對象引用類型,[ reference 數組引用類型
以上是“JVM中Java字節碼文件的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。