lambda java,java--迭代(三)foreach解析與字節碼

 2023-11-19 阅读 22 评论 0

摘要:foreach循環也叫增強型的for循環,他是JDK 5.0的新特性(其他特性例如泛型等) 使用方法如下: for(type element:array){....//coding here } ? lambda java,其中關于foreach的優勢與局限性在迭代(二)文章中都有指出,并且在上

foreach循環也叫增強型的for循環,他是JDK 5.0的新特性(其他特性例如泛型等)

使用方法如下:

for(type element:array){....//coding here      
}

?

lambda java,其中關于foreach的優勢與局限性在迭代(二)文章中都有指出,并且在上一篇文章提出了關于foreach如何具體實現的問題。

我們通過反編譯.class文件(語法為:javap -verbose xxxx.class),得到了如下內容:

java final。其實反編譯后的信息很多,但是我只截取了最重要的兩部分。至于這兩部分分別代表什么,我們先來了解java的字節碼怎么讀取。當我講述完成的時候,相信也是能夠讀懂上面信息的時候。

?

首先我們打開.class文件:顯示如下:

Java foreach??

很清晰的看到是一連串的十六進制組成,這就是匯編形成的字節碼,接下來我們對如何解讀字節碼進行進一步的分析:

?

首先,我們來看一副圖:

必須聲明元素類型foreach、

這幅圖就是字節碼的結構圖,組成部分就分別是這么幾個,我將分別進行闡述;

?

1)魔數(Magic Number)

四個字節的魔數,從我給出的.class文件看出,開頭的四個字節是cafebabe,當然這是十六進制的數,但是為什么是cafebabe。看看java的圖標吧:

list.foreach??

?

2)版本號:

版本號四個字節,前四個為次版本號,后四個為主版本號,在此,值為0x0000 0034,解析出來就是次版本號為0,主版本號為52;那么,從反編譯出來的第一幅圖可以看到:

java arraylist,

這就是反編譯出來的版本號,與我們分析的一致;

至此,前八個字節很簡單就被我們分析出來了。

?

3)常量池

java中foreach循環用法?接著就是常量池入口。

常量池是class文件中的資源倉庫,主要包括兩大類:字面量和符號引用。字面量如文本字符串,java申明中為final的值,而符號引用入類和接口的全局限定名,字段的名稱和描述符,方法的名稱和描述符。 具體怎么實現在內存內存中,則是虛擬機的工作,我們這里還是不要深入比較好。

在進行常量池分析的時候,我們先了解常量池類型表:

?

?

上面描述了11中數據類型的結構,但是jdk1.7后又增加了三種,分別是(CONSTANT_MethodHandle_info,CONSTANT_MethodType_info以及CONSTANT_InvokeDynamic_info)算起來一共是14中,接下來按照demo碼對他們進行解答:

0x0048:這是緊接著版本號的,因為常量池的數量不一定,所以我們在入口的時候需要定義一個u2類型的數據來記錄到底有多少個常量池,該十六進制表示有71個常量池,這里要注意:該十六進制轉換數值為72,但是實際只有71個常量池!!?縮影范圍為1-71,第0項被設計者規定空留出來了,這是.class文件格式所規定的。

所以我們接下來要翻譯71個常量池。(不可能的,我舉例子出來能夠引用就可以了):

?

#1: 0x07:tag值為7:class-info,一個U2類型縮影為:0x0002,即#2;

#2:0x01:tag值為1:utf-8info,長度:0x0019:byte長度其實就是這個描述的具體內容,是從一個字節大小擴展出去的。應該是25個字節(0x0019)。還記得我們使用16進制打開的.class文件么?旁邊有一串字符,其中包含亂碼,中間的某些字符串和16進制的值時一一對應的,采用的asc碼。所以,這一段字符的值和16進制對應關系如截圖所示:

當然長度只有25字節,所以在25字節過后,是下一個常量池信息了!也就是在07及其以后的數值已經是下一個常量池了。

?

上面兩個例子其實就可以很好的解釋了,我這個例子的常量池有點長,我這里給出另外一位博主的網站地址,他所舉出的例子是很詳細的。http://www.importnew.com/24088.html。

我們可以看到,我們自己分析的結果其實就是反編譯出來的結果的第一部分。

4)Access_Flag訪問標志:

訪問標志信息包括這個.class文件是類還是接口,是不是public,是不是abstract,如果是類是否被聲明成final:

下面給出這個標志表格:

而我們在給出的.class文件中會發現,此處的標志信息為0x0021。這其實是很簡單,0x0020與0x0001的并集。即包含了兩個標志信息,這里匯編器自動將這個類歸類為超類。

?

5)類索引

類索引引用與確定類的全限定名

0x0001表示引用第一個索引,就是:#1.#2.iteretorTest/TestIterator.

6)超類索引

與類索引一致,確定超類的全限定名

0x0003表示引用第三個索引,就是:#3.#4. java/lang/Object;

7)接口索引

可以看到接口索引為2+n個字節,而我們的測試程序沒有應用接口,所以我們的前兩個字節是0x0000。那么,也不存在n的情況。但是如果有接口,這個時候后面直接跟著接口的索引。

8)字段表集合

字段表用于描述類和接口中聲明的變量。這里的字段包含了類級別變量以及實例變量,但是不包括方法內部聲明的局部變量。

而且,字段表也是2+n個字節,在本文的例子中,我們沒有變量,所以在.class文件中,這里為0x0000;

但是,實際上,很多情況下都會涉及到包含變量。

這個時候,我們給出字段表集合,來對這段字段進行分析;

同樣,用上面給出博主的文章中的例子可以在此分析一下。

?

下面就是方法,我們將在下一篇文章中寫出,方法的解析就會相交前面的復雜很多,其中某些字符的含義需要單獨解釋,例如<init>,()V,我將會用一個單獨的篇章進行方法的字節碼解析。

?

轉載于:https://www.cnblogs.com/DSNFZ/articles/7599627.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/184005.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息