標籤:傳遞 anti help 自己的 i++ version 語言 head lan
Reference
- javap 基本使用方法
- 深入理解java位元組碼
- 從Java代碼到位元組碼
- Java位元組碼.class檔案案例分析
位元組碼 核心概念
Class檔案是8位位元組流,按位元組對齊。之所以稱為位元組碼,是由於每條指令都僅僅佔領一個位元組。全部的作業碼和運算元都是按位元組對齊的。
資料結構
Java虛擬機器規範中規定。Class檔案格式採用一種相似C語言結構體的偽結構來儲存,它僅僅有兩種資料類型
無符號數(基礎資料型別 (Elementary Data Type))
主要用於描寫敘述數字、索引引用、數量值、或UTF-8編碼構成的字串;
u1 – 1個位元組
u2 – 2個位元組
u4 – 4個位元組
u8 – 8個位元組
表(複合資料型別)
用於描寫敘述有層次關係的複合結構的資料。
習慣性以“_info”結尾
Class檔案格式
| 資料類型 |
名稱 |
數量 |
| u4 |
magic |
1 |
| u2 |
minor_version |
1 |
| u2 |
major_version |
1 |
| u2 |
constant_pool_count |
1 |
| cp_info |
constant_pool |
constant_pool_count + 1 |
| u2 |
access_flags |
1 |
| u2 |
this_class |
1 |
| u2 |
super_class |
1 |
| u2 |
interfaces_count |
1 |
| u2 |
interfaces |
interfaces_count |
| u2 |
fields_count |
1 |
| field_info |
fields |
fields_count |
| u2 |
methods_count |
1 |
| method_info |
methods |
methods_count |
| u2 |
attributes_count |
1 |
| attribute_info |
attributes |
attributes_count |
class說明
- magic: Class檔案的頭4個位元組,它的唯一作用是用於確認該檔案是否是能被JVM接受的Class檔案
- minor_version :第5和第6位元組是次版本號碼號
- major_version:第7和第8位元組是主要版本號號
constant_pool_count: 常量池大小
cp_info : 複合資料結構,是一組常量資料結構,有11種常量資料結構
access_flags :訪問標誌,access_flags的計算公式為:access_flags = flagA | flagB | flagB …
field_info :欄位表(field_info)用於描寫敘述類或介面中聲明的變數,它包括類變數、執行個體變數,但不包括方法內的局部變數和塊變數。和cp_info部分不一樣。cp_info由於常量類型的不一樣其資料結構有11種,但field_info的結構僅僅有一種。
(資料結構例如以下)
欄位訪問標誌。和類的訪問標誌,由於修飾符不同稍有不同,具體見。
method_info:方法表集合(method_info)和欄位表集合的結構是一致的,僅僅是訪問標誌不同。
attribute_info:用於在Class檔案、欄位表、方法表中攜帶自己的屬性工作表集合,以用於描寫敘述某些情境的專有資訊。
Java程式方法體裡面的代碼經過javac編譯器處理過後將終於位元組碼儲存在Code屬性內。抽象類別或介面中的方法不存在Code屬性。
SourceFile:SourceFile屬性主要記錄產生這個Class檔案的源碼名稱,也屬於可選屬性,能夠使用javac的-g:none或-g:source選項來關閉或要求產生這些資訊。
LocalVariableTable:LocalVariableTable屬性用於描寫敘述棧幀中局部變數表中的變數與Java源碼定義的變數之間的關係,可是這樣的關係並不是執行時必須,預設也不會產生到Class檔案裡,能夠通過javac中使用-g:none或-g:vars選項取消或者產生這項資訊。
LineNumberTable:LineNumberTable屬性用於描寫敘述Java源碼行號和位元組碼行號(位元組碼的位移量)之間的相應關係,它不是執行時必須屬性。但預設會產生到Class檔案裡。
也能夠在javac中使用-g:none或-g:lines選項來取消或顯示產生這一部分資訊。
具體參見 Java位元組碼.class檔案案例分析
jvm執行淺談
Java虛擬機器(JVM)是基於棧結構的。對於最初的main方法產生的全部的方法調用,都會在棧中產生一個幀。這些幀各自包括一組局部變數,這組局部變數就是這種方法在執行過程中所需的全部變數,包括一個指向this的引用、該方法的全部參數以及其它局部定義的變數。對於類方法(即static方法),其參數列表從0開始算起。而對於執行個體方法。位置0是用來儲存this引用。
class執行就是jvm順序執行一條條儲存在Code中的指令,例如以下所看到的:
動態過程,例如以下:
public class Demo { public static void foo() { int a = 1; int b = 2; int c = (a + b) * 5; }}
具體參見
- 深入理解java位元組碼
- 從Java代碼到位元組碼
javap 反組譯碼
javap是JDK內建的反組譯碼器。能夠查看java編譯器為我們產生的位元組碼。通過它,我們能夠對比源碼和位元組碼。從而瞭解非常多編譯器內部的工作。
文法:
javap [ 命令選項 ] class…
javap 命令用於解析類檔案。其輸出取決於所用的選項。
若沒有使用選項。javap 將輸出傳遞給它的類的 public 域及方法。javap 將其輸出到標準輸出裝置上。
命令選項
-help 輸出 javap 的協助資訊。
-l 輸出行及局部變數表。
-public 僅僅顯示 public 類及成員。
-protected 僅僅顯示 protected 和 public 類及成員。
-package 僅僅顯示包、protected 和 public 類及成員。這是預設設定。
-private 顯示全部類和成員。
-s 輸出內部類型簽名。
-c 輸出類中各方法的未解析的代碼。即構成 Java 位元組碼的指令。
-verbose 輸出堆棧大小、各方法的 locals 及 args 數,以及class檔案的編譯版本號碼
-classpath[路徑] 指定 javap 用來尋找類的路徑。假設設定了該選項,則它將覆蓋預設值或 CLASSPATH 環境變數。檔案夾用冒號分隔。
-bootclasspath[路徑] 指定載入自舉類所用的路徑。
預設情況下,自舉類是實現核心 Java 平台的類。位於 jrelib以下。
-extdirs[dirs] 覆蓋搜尋安裝方式擴充的位置。
擴充的預設位置是 jrelibext。
Java位元組碼 小結