日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java jpg结构_Java Class 字节码文件结构分析----附带逐字节码分析图

發布時間:2024/7/23 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java jpg结构_Java Class 字节码文件结构分析----附带逐字节码分析图 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

歡迎訪問我的博客,同步更新: 楓山別院 今天給大家分享下Java Class字節碼文件的結構解析。(文末附有詳細大圖)

代碼

首先我們創建一個Java類,然后添加一些成員變量和方法,如下:

public class Test {

String name = "hello";

int size = 10;

long num = 100;

Double pi = 3.14;

public static void main(String[] args) {

Test test = new Test();

test.print();

}

public void print() {

System.out.print(name);

}

}

大家可以看到,這是一個非常簡單的類,僅僅有幾個基本類型的成員變量和兩個簡單的方法。這是為了我們分析Class文件方便起見,沒有添加復雜的結構。

編譯

然后大家可以用javac命令編譯一下這個類。編譯之后,我們就得到了一個class文件,用sublime之類的軟件打開這個class文件,我們可以看到如下信息:

CA FE BA BE 00 00 00 34 00 40 0A 00 11 00 29 08

00 2A 09 00 0C 00 2B 09 00 0C 00 2C 05 00 00 00

00 00 00 00 64 09 00 0C 00 2D 06 40 09 1E B8 51

..........

00 00 00 0C 00 01 00 00 00 0B 00 1F 00 20 00 00

00 01 00 27 00 00 00 02 00 28

是一行一行的十六進制的字符,每兩個字符是一個字節,每個字節之間用空格分隔,我省略掉了中間的多行數據,如果要看完整數據,請看文末。

這些就是編譯之后的信息了,文件中的字符在我們看來只是一行一行字符,其實是劃分格式的。我們來看一下是如何劃分的。

結構

Class文件的結構,是一個結構體,有以下元素,描述如下:

ClassFile {

u4 magic; //魔數

u2 minor_version; //Java的次版本號

u2 major_version; //Java的主版本號

u2 constant_pool_count; //常量池的長度

cp_info constant_pool[constant_pool_count]; //常量池數組

u2 access_flags; //類訪問標志

u2 this_class; //類名索引

u2 super_class; //父類名索引

u2 interface_count; //實現的接口的數量

u2 interfaces[interface_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]; //屬性數組

}

左邊u2,u4都是表示字節的長度,u2是兩字節,u4是四字節。右邊是元素的名稱。

Class文件就是由以上元素,一個緊挨一個組成的。總體的結構還是不復雜的,開頭的三個值,magic,minor_version,major_version和中間的access_flags,this_class,super_class,他們是固定的位置,固定的字節長度。其他的數量不一定的值,都是一個長度,然后后面就是緊跟著該長度的數組,存儲著該組值。數組結構通常都有下一級的子結構。

我把字節文件按照上面的元素格式,以不同的顏色劃分了出來,請大家看下結構圖:

class-simple.png

看圖非常的一目了然,讀兩遍書,不如看一遍圖啊。

連續的相同顏色的格子,是同一種元素的值。元素之間是緊緊的排列在一起,大家可以看到結構非常的緊湊,節省空間。看不清的同學可以下載下來,放大一下看。

分析

1. magic 魔數

我們知道有時候通過后綴識別文件是不準確的,因為很容易就改掉后綴。所以很多文件格式,在文件的開頭寫上幾個固定的值,為了識別方便該種格式。比如PDF文件的開頭是“%PDF”,這個固定的值,就叫魔數,其實就是個標識。class文件的魔數就是“CA FE BA BE”,JVM讀取開頭的四個字節,如果是這個值,那么就認為這個文件是個class。

magic.jpg

2. version 版本號

魔數之后,是版本號,大家可以看到,我們有兩部分的版本號。第一個版本號就是次版本號,第二個是主版本號。比如52.0,52是主版本號,0是次版本號。這個版本是為了讓JVM識別編譯這個clas文件的Java版本,比如Java SE8,對應的版本號是52.0,Java SE7 是51.0,Java SE6 是50.0。如果一個最高只支持Java SE7版本的JVM,讀取到一個52.0,那么它可能是執行不了這個class的,以為它是Java SE8編譯出來的,可能用了JavaSE8的新特性。

version.jpg

3. constant_pool 常量池

常量池占用了class中非常多的空間,存放著非常多的信息,包括數字,字符串,類和接口的名字,字段和方法的名字等等。上來先是常量池的數量,也就是常量池數組的長度。后面緊跟著就是數組的內容,非常長,結構也不太一樣。大家可以仔細看看附錄中的詳細圖,太大了,在這就不截圖了。

常量池中元素的子結構雖然有非常多的種類,但是都差不多的。首先是tag,tag的值表示這個元素是一個什么類型,也就是一個什么數據結構,然后JVM就可以根據這個結構來解析數據了。一般的XXX_index就是一個索引,length就是一個長度,bytes中是該元素存儲的值。結構非常多,我們后面單獨一篇文章介紹下這里。

4. access_flags 類訪問標志

access_flags保存的信息是,該類的訪問標志,比如是public還是private,是個接口還是個類,或者枚舉,等等。

access_flags.jpg

此處 access_flags的值是0x0021,代表什么意思呢?我們需要看個表格:

名稱

說明

ACC_PUBLIC

0x0001

public類型

ACC_FINAL

0x0010

final修飾符

ACC_SUPER

0x0020

使用invokespecial字節碼指令,在JDK1.2之后添加

ACC_INTERFACE

0x0200

接口

還有好幾種類型,我們就先看這些。我們的值是0x0021,好像沒有這個值對應的類型。其實是,0x0020 加上 0x0001,也就是說0x0021表示ACC_PUBLIC和ACC_SUPER。也就是說,這是個public訪問級別的類。

5. this_class 類名索引

this_class元素保存的是類的全限定類名,即包路徑加類名。為什么還有個索引呢?因為這個地方保存的不是具體的全限定類名的字符串,是一個索引值。這個索引是常量池的索引,也就是說,其實真正的全限定類名字符串是在常量池存著呢。我們在附錄的詳細表中找一下這個值,找到第39行數據的最后,是this_class的位置。

this_class

它的值是0x000c,是十進制的12對吧?我們找常量池中的索引是12的值,在第4行最后。

index_12.jpg

很奇怪,這個地方比不是我們說的全限定類名字符串,是一個叫 name_index的索引。其實這個位置存放的數據,是有一個子結構的,它由tag和 name_index組成。tag的值是7,這個值7代表了一種數據結構,就是 CONSTANT_Class_info,這個類型保存的值是類或者接口的符號引用。又是一個引用,也就是索引。從表上我們可以知道,這個索引的值是49,OK,我們再從常量池找索引49的值。

index_49.jpg

在第26和27行上,我們終于找到了類的全限定名稱。

6. super_class 父類名索引

super_class跟this_class是一樣的,不過這里保存的是類的父類全限定名稱而已。大家可以自己找一下看看。不過需要注意的是,如果沒有明確指定某個類的父類,在Java中默認父類都是java.lang.Object,而java.lang.Object本身是沒有父類的,所以如果是Object類,它的super_class值就是0。

7. interfaces 接口池

接著就是接口索引表或者說是接口池了,這里保存類實現的接口。

interfaces.jpg

因為我們的類沒有實現接口,所以它的長度是0,后面的數組自然也就省略了。

8. fields 字段池

fields.jpg

接著是我們的字段信息。從 fields_count的值我們可以知道有4個字段,這跟我們在代碼中的字段數量是一致的。然后緊接著就是字段數組了。字段數組中的元素是有數據結構的。如下:

field_info {

u2 access_flags; //變量的訪問標識符

u2 name_index; //名稱索引

u2 descriptor_index; //類型信息索引

u2 attributes_count; //自定義屬性長度

attribute_info attributes[attributes_count]; //自定義屬性池

}

name_index中存的就是字段名字的索引,老規矩大家自己找一下。access_flags是變量的訪問標識符,descriptor_index保存的是變量的類型信息。最后剩下的屬性,為什么有了類的屬性池還會在這里有個字段下的屬性池呢?這個字段下的屬性池是留給JVM來自定義拓展的,各個JVM實現可能會不一樣,JVM遇到識別不了的屬性會自動跳過。

9. methods 方法池

大家可以看到,在附錄詳細大圖中,方法池沒有展開詳細的結構,這是因為這里太復雜了,展開圖不太好畫,我太懶了,所以沒畫,哈哈哈哈。依然是上來就是一個長度,3個方法,后面跟著一個數組。有人要問了,不對啊,怎么是3個方法,我們只寫了2個。那是因為還有個類的默認構造方法,忘了吧,哈哈。后面有機會我們詳細分析方法池的結構。

10. attributes 屬性池

屬性池這個地方,跟常量池一樣,保存了很多信息,不過我們這個類中的屬性信息較少。屬性也有很多的子結構,而且不同的JVM實現還可能會有自己的屬性值,這里我們后面有機會單獨說一下,大家現在知道即可。

附錄

最后,附上一張非常詳細的大圖,我在圖中畫出了更詳細的結構,包括常量池中子元素的結構,每個字節對應的值是什么等等,非常詳細,也耗費了我很多時間,希望對大家有用。大家可以下載下來,經常看一看。

class.png

總結

以上是生活随笔為你收集整理的java jpg结构_Java Class 字节码文件结构分析----附带逐字节码分析图的全部內容,希望文章能夠幫你解決所遇到的問題。

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