class對象和class文件_Class文件格式

?我們知道Java是一門跨平臺的語言,我們編寫的Java代碼會被編譯成中間class文件以讓Java虛擬機解析運行。而Java虛擬機規范僅僅描述了抽象的Java虛擬機,在實現具體的Java虛擬機時,僅指出了設計規范。Java虛擬機的實現必須體現規范中的內容,但僅在確有必要時才應該受制于這些規范。對于完整內容,可以查看原文檔,以JDK7為例,可查看https://docs.oracle.com/javase/specs/jvms/se7/html/,或者《深入理解Java虛擬機 JVM高級特性與最佳實踐》一書。完整的規范主要包含以下內容:

  • 第2章:概覽Java虛擬機整體架構
  • 第3章:介紹如何將Java語言編寫的程序轉換為虛擬機指令集
  • 第4章:定義class文件格式。它是一種與硬件和操作系統無關的二進制格式,用來表示編譯后的類和接口
  • 第5章:定義了Java虛擬機啟動以及類和接口的加載、鏈接和初始化的過程
  • 第6章:定義了Java虛擬機指令集
  • 第7章:提供了一張以操作碼值為索引的Java虛擬機操作碼助記表

?本文只是大概記錄項目需要了解的基礎概念,著重在介紹Class文件格式上,為該系列后續內容做鋪墊。

?Class文件是一組以8字節為基礎單位的二進制流,各個數據項目嚴格按照順序緊湊排列在class文件中,中間沒有任何分割符。每個 Class 文件都是由 8 字節為單位的字節流組成,所有的 16 位、32 位和 64 位長度的數據將被構造成 2 個、4 個和 8 個 8 字節單位來表示。

?每一個Class文件對應于一個如下所示的ClassFile結構體:

6748d90d21eda9b47af63dde5463aed3.png

涉及到的內容包括:

  • magic:魔數,魔數的唯一作用是確定這個文件是否為一個能被虛擬機所接受的Class文件。魔數值固定為0xCAFEBABE,不會改變。
  • minor_version、major_version:副版本號和主版本號,minor_version和major_version的值分別表示Class文件的副、主版本。一個Java虛擬機實例只能支持特定范圍內的主版本號(Mi至Mj)和0至特定范圍內(0至m)的副版本號。
  • constant_pool_count:常量池計數器,constant_pool_count的值等于constant_pool表中的成員數加1。
  • constant_pool[]:常量池,constant_pool是一種表結構,它包含Class文件結構及其子結構中引用的所有字符串常量、類或接口名、字段名和其它常量。
  • access_flags:訪問標志,access_flags是一種掩碼標志,用于表示某個類或者接口的訪問權限及基礎屬性。
  • this_class:類索引
  • super_class:父類索引
  • interfaces_count:接口計數器,interfaces_count的值表示當前類或接口的直接父接口數量
  • interfaces[]:接口表,在interfaces[]數組中,成員所表示的接口順序和對應的源代碼中給定的接口順序(從左至右)一樣,即interfaces[0]對應的是源代碼中最左邊的接口。
  • fields_count:字段計數器,fields_count的值表示當前Class文件fields[]數組的成員個數。
  • fields[]:字段表,fields[]數組描述當前類或接口聲明的所有字段,但不包括從父類或父接口繼承的部分。
  • methods_count:方法計數器,methods_count的值表示當前Class文件methods[]數組的成員個數。
  • methods[]:方法表,methods[]數組只描述當前類或接口中聲明的方法,不包括從父類或父接口繼承的方法。
  • attributes_count:屬性計數器,attributes_count的值表示當前Class文件attributes表的成員個數。
  • attributes[]:屬性表

?可用jdk自帶的javap命令對class文件進行反編譯,以查看內容,如下代碼:

public class Ex { public void judgeAge(int age) { int step = 0; if (age > 18) { step++; System.out.println("a litter old"); } else { System.out.println("a litter cute"); step++; } System.out.println(step); } public static void main(String[] args) { Ex ex = new Ex(); ex.judgeAge(16); }}

執行 javap -verbose -p Ex.class的結果為

Classfile Ex.class Last modified 2019-11-29; size 788 bytes MD5 checksum 8b5d8ebf38c4441fe7150c10da31ce1b Compiled from "Ex.java"public class Ex minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Methodref #10.#31 // java/lang/Object."":()V #2 = Fieldref #32.#33 // java/lang/System.out:Ljava/io/PrintStream; #3 = String #34 // a litter old #4 = Methodref #35.#36 // java/io/PrintStream.println:(Ljava/lang/String;)V #5 = String #37 // a litter cute #6 = Methodref #35.#38 // java/io/PrintStream.println:(I)V #7 = Class #39 // Ex #8 = Methodref #7.#31 // Ex."":()V #9 = Methodref #7.#40 // Ex.judgeAge:(I)V #10 = Class #41 // java/lang/Object #11 = Utf8  #12 = Utf8 ()V #13 = Utf8 Code #14 = Utf8 LineNumberTable #15 = Utf8 LocalVariableTable #16 = Utf8 this #17 = Utf8 LEx; #18 = Utf8 judgeAge #19 = Utf8 (I)V #20 = Utf8 age #21 = Utf8 I #22 = Utf8 step #23 = Utf8 StackMapTable #24 = Utf8 main #25 = Utf8 ([Ljava/lang/String;)V #26 = Utf8 args #27 = Utf8 [Ljava/lang/String; #28 = Utf8 ex #29 = Utf8 SourceFile #30 = Utf8 Ex.java #31 = NameAndType #11:#12 // "":()V #32 = Class #42 // java/lang/System #33 = NameAndType #43:#44 // out:Ljava/io/PrintStream; #34 = Utf8 a litter old #35 = Class #45 // java/io/PrintStream #36 = NameAndType #46:#47 // println:(Ljava/lang/String;)V #37 = Utf8 a litter cute #38 = NameAndType #46:#19 // println:(I)V #39 = Utf8 Ex #40 = NameAndType #18:#19 // judgeAge:(I)V #41 = Utf8 java/lang/Object #42 = Utf8 java/lang/System #43 = Utf8 out #44 = Utf8 Ljava/io/PrintStream; #45 = Utf8 java/io/PrintStream #46 = Utf8 println #47 = Utf8 (Ljava/lang/String;)V{ public Ex(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LEx; public void judgeAge(int); descriptor: (I)V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=2 0: iconst_0 1: istore_2 2: iload_1 3: bipush 18 5: if_icmple 22 8: iinc 2, 1 11: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 14: ldc #3 // String a litter old 16: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 19: goto 33 22: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 25: ldc #5 // String a litter cute 27: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 30: iinc 2, 1 33: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 36: iload_2 37: invokevirtual #6 // Method java/io/PrintStream.println:(I)V 40: return LineNumberTable: line 4: 0 line 5: 2 line 6: 8 line 7: 11 line 9: 22 line 10: 30 line 12: 33 line 13: 40 LocalVariableTable: Start Length Slot Name Signature 0 41 0 this LEx; 0 41 1 age I 2 39 2 step I StackMapTable: number_of_entries = 2 frame_type = 252 /* append */ offset_delta = 22 locals = [ int ] frame_type = 10 /* same */ public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=2, args_size=1 0: new #7 // class Ex 3: dup 4: invokespecial #8 // Method "":()V 7: astore_1 8: aload_1 9: bipush 16 11: invokevirtual #9 // Method judgeAge:(I)V 14: return LineNumberTable: line 16: 0 line 17: 8 line 18: 14 LocalVariableTable: Start Length Slot Name Signature 0 15 0 args [Ljava/lang/String; 8 7 1 ex LEx;}SourceFile: "Ex.java"

下面對后續需要接觸到的幾項內容做說明。

1. 數據項

?Class文件中有兩種數據類型,分別是無符號數和表:

98ed6d70c4e38817b6798c95980ec951.png
  • 無符號數:屬于基本數據類型,主要可以用來描述數字、索引符號、數量值或者按照UTF-8編碼構成的字符串值,大小使用u1、u2、u4、u8分別表示1字節、2字節、4字節和8字節
  • 表:是由多個無符號數或者其他表作為數據項構成的復合數據類型,所有的表都習慣以“_info”結尾

2. 訪問和修飾符標識

fdbc978474cae85ac1e67fe58f2d82d4.png

?帶有 ACC_SYNTHETIC 標志的部分,意味著它是由編譯器自己產生的而不是由程序員編寫的源代碼生成的。有該標志的類、屬性、方法等不會在源碼中顯示。

3. 類型描述符

8df97907a55e6cc616bdc9e825f3c54a.png

?基本類型的描述是單個字符:

  • Z表示 boolean
  • C表示 char
  • B表示 byte
  • S表示 short
  • I 表示 int
  • F 表示 float
  • J 表示 long
  • D 表示 double
  • 一個類類型的描述符是這個類的內部名,前面加上字符 L,后面跟有一個分號。例如,String 的類型描述符為 Ljava/lang/String;。而一個數組類型的 述符是一個方括號后面跟有該數組元素類型的描述符。

4. 方法描述符

?方法描述符是一個類型描述符列表,它用一個字符串描述一個方法的參數類型和返回類型。

?方法描述符以左括號開頭,然后是每個形參的類型描述,然后是一個右括號,接下來是返回類型的類型描述符,如果該方法返回void,則是 V,表示方法描述中不包含方法的名字或參數名,可看如下例子:

3d0a073712e843557bfce937e1b09c31.png

5. 指令

?Java虛擬機的指令由一個字節長度的、代表著某種特定操作含義的操作碼(Opcode)以及跟隨其后的零至多個代表此操作所需參數的操作數(Operands)所構成。虛擬機中許多指令并不包含操作數,只有一個操作碼。

?常見的指令如下:

  • 字段訪問指令:getfield,putfield,getstatic,pustatic
  • 比較指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp
  • 跳轉指令:ifeq,iflt,ifle,ifne,ifgt,ifge,ifnull,ifnonnull
  • 比較條件跳轉指令:ificmpeq,ificmpne,ificmplt,ificmpgt,ificmple,ificmpge,ifacmpeq,ifacmpne
  • 多條件分支跳轉:tableswitch和lookupswitch
  • 無條件跳轉:goto
  • 函數調用與返回指令
  • 函數調用指令:invokevirtual,invokeinterface,invokespecial,invokestatic,invokedynamic;
  • 函數返回:需要將返回值壓入調用者操作數棧,需要使用xreturn指令(x可以是i,l,f,d,a或空)

?PS:筆者個人習慣使用Bytecode Outline進行反編譯,這款插件輸出的內容可讀性會高點,上面的內容輸出下:

// class version 52.0 (52)// access flags 0x21public class Ex { // compiled from: Ex.java // access flags 0x1 public ()V L0 LINENUMBER 1 L0 ALOAD 0 INVOKESPECIAL java/lang/Object. ()V RETURN L1 LOCALVARIABLE this LEx; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x1 public judgeAge(I)V L0 LINENUMBER 4 L0 ICONST_0 ISTORE 2 L1 LINENUMBER 5 L1 ILOAD 1 BIPUSH 18 IF_ICMPLE L2 L3 LINENUMBER 6 L3 IINC 2 1 L4 LINENUMBER 7 L4 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; LDC "a litter old" INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V GOTO L5 L2 LINENUMBER 9 L2 FRAME APPEND [I] GETSTATIC java/lang/System.out : Ljava/io/PrintStream; LDC "a litter cute" INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L6 LINENUMBER 10 L6 IINC 2 1 L5 LINENUMBER 12 L5 FRAME SAME GETSTATIC java/lang/System.out : Ljava/io/PrintStream; ILOAD 2 INVOKEVIRTUAL java/io/PrintStream.println (I)V L7 LINENUMBER 13 L7 RETURN L8 LOCALVARIABLE this LEx; L0 L8 0 LOCALVARIABLE age I L0 L8 1 LOCALVARIABLE step I L1 L8 2 MAXSTACK = 2 MAXLOCALS = 3 // access flags 0x9 public static main([Ljava/lang/String;)V L0 LINENUMBER 16 L0 NEW Ex DUP INVOKESPECIAL Ex. ()V ASTORE 1 L1 LINENUMBER 17 L1 ALOAD 1 BIPUSH 16 INVOKEVIRTUAL Ex.judgeAge (I)V L2 LINENUMBER 18 L2 RETURN L3 LOCALVARIABLE args [Ljava/lang/String; L0 L3 0 LOCALVARIABLE ex LEx; L1 L3 1 MAXSTACK = 2 MAXLOCALS = 2}

更多原創內容請搜索微信公眾號:啊駝(doubaotaizi)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/393613.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393613.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393613.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2018計算機應用基礎考試6,2018結構工程師《計算機應用基礎》試題(6)

大家做好準備迎接2018考試了嗎?出國留學網為您整理了“2018結構工程師《計算機應用基礎》試題(6)”,跟著出國留學網來了解一下吧。要相信只要自己有足夠的實力,無論考什么都不會害怕!2018結構工程師《計算機應用基礎》試題(6)1、下列存儲器中&#xff0…

leetcode1282. 用戶分組(貪心算法)

有 n 位用戶參加活動,他們的 ID 從 0 到 n - 1,每位用戶都 恰好 屬于某一用戶組。給你一個長度為 n 的數組 groupSizes,其中包含每位用戶所處的用戶組的大小,請你返回用戶分組情況(存在的用戶組以及每個組中用戶的 ID&…

mysql解鎖_mysql 解鎖

show OPEN TABLES where In_use > 0;show processlist;show status like Table%;show status like %lock%;show OPEN TABLES where In_use > 0;//1.查看當前數據庫鎖表的情況SELECT * FROM information_schema.INNODB_TRX;//2.殺掉查詢結果中鎖表的trx_mysql_…

強制換行和禁止換行

強制換行:word-break: break-all; 只對英文起作用,以字母作為換行依據word-wrap: break-word; 只對英文起作用,以單詞作為換行依據white-space: pre-wrap; 只對中文起作用,強制換行禁止換行:white-space: now…

構建自己的簡單微服務架構(開源)

構建自己的簡單微服務架構(開源) 原文:構建自己的簡單微服務架構(開源)前言 本篇僅作引導,內容較多,如果閱讀不方便,可以使用電腦打開我們的文檔官網進行閱讀。如下圖所示&#…

職業生涯愿景計算機,職業生涯愿景

《職業生涯愿景》由會員分享,可在線閱讀,更多相關《職業生涯愿景(10頁珍藏版)》請在人人文庫網上搜索。1、職業生涯愿景職業生涯愿景設備安裝技術是掌握本專業必需的基本理論知識,具有設備制造、安裝、調試、管理、設計。施工方案編制的專業技…

leetcode881. 救生艇(貪心算法加雙指針)

第 i 個人的體重為 people[i],每艘船可以承載的最大重量為 limit。 每艘船最多可同時載兩人,但條件是這些人的重量之和最多為 limit。 返回載到每一個人所需的最小船數。(保證每個人都能被船載)。 示例 1: 輸入:people [1,2]…

react避免子組件渲染_如何與React一起使用正確的方法來避免一些常見的陷阱

react避免子組件渲染One thing I hear quite often is “Let’s go for Redux” in our new React app. It helps you scale, and the App data shouldn’t be in React local state because it is inefficient. Or when you call an API and while the promise is pending, th…

[轉載]Spring配置文件詳解一:

2019獨角獸企業重金招聘Python工程師標準>>> 原文地址&#xff1a;Spring配置文件詳解一&#xff1a;<context:annotation-config/>與<context:component-scan base-package"com.xx 作者&#xff1a;愛情隨遇而安 <context:annotation-config/>…

mysql 8.0.16修改root密碼_mysql 8.0.16 winx64及Linux修改root用戶密碼 的方法

連接數據庫等基礎操作請自行解決哈&#xff0c;本篇是重點記錄如何改密碼。一、查詢用戶密碼:查詢用戶密碼命令&#xff1a;select host, user, authentication_string from mysql.user ;host&#xff1a;允許用戶登錄的ip‘位置%表示可以遠程&#xff1b;user&#xff1a;當前…

舞臺設計

舞臺設計 #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdio> #include<queue> using namespace std;int ucol[1005],dcol[1005],lrow[1005],rrow[1005]; int numr[1005],numc[1005]; int a[100…

LoadRunner11支持的瀏覽器小結

LoadRunner11支持的瀏覽器小結轉載于:https://www.cnblogs.com/zwh-Seeking/articles/11060154.html

手機計算機的隱藏小技巧,漲知識!MIUI計算器原來有這么多隱藏小技巧,最后一個絕對想不到...

原標題&#xff1a;漲知識&#xff01;MIUI計算器原來有這么多隱藏小技巧&#xff0c;最后一個絕對想不到計算器除了我們需要進行日常的計算以外&#xff0c;幾乎是用不到的。但是MIUI中的計算器與普通計算器可不同&#xff0c;里面的隱藏小技巧足以讓你震驚到&#xff0c;那么…

如何使用JavaScript中的工廠函數構建可靠的對象

Discover Functional JavaScript was named one of the best new Functional Programming books by BookAuthority!“發現功能JavaScript”被BookAuthority評為最佳新功能編程書籍之一 &#xff01; I suggest to take into consideration these ideas for building reliable …

leetcode99. 恢復二叉搜索樹(優先隊列)

二叉搜索樹中的兩個節點被錯誤地交換。請在不改變其結構的情況下&#xff0c;恢復這棵樹。示例 1:輸入: [1,3,null,null,2]1/3\2輸出: [3,1,null,null,2]3/1\2代碼 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* …

Android零基礎入門第83節:Activity間數據傳遞方法匯總

2019獨角獸企業重金招聘Python工程師標準>>> 在Activity間傳遞的數據一般比較簡單&#xff0c;但是有時候實際開發中也會傳一些比較復雜的數據&#xff0c;本節一起來學習更多Activity間數據的傳遞。 一、常用數據類型 在前面幾節我們只學習了一些常用類型的數據傳遞…

mysql gz 安裝_Linux下安裝mysql 5.7.17.tar.gz的教程詳解

1.創建MySQL組和mysql用戶groupadd mysqluseradd -r -g mysql mysql2.拷貝&#xff1a;cp -R mysql-5.7.16-linux-glibc2.5-i686 /usr/local/mysql3.創建data目錄mkdir /usr/local/mysql/data3.安裝數據庫切換到/usr/loca/mysql目錄下cd /usr/local/mysql修改當前目錄的所有者為…

02-c#基礎之01-基礎語法(一)

1.注釋符 1&#xff09;注銷 2) 解釋 2.C#中的3種注釋符 1&#xff09;單行注釋// 2)多行注釋/*要注釋的內容*/ 3)文檔注釋///多用來解釋類或者方法 2.VS中的快捷鍵 轉載于:https://www.cnblogs.com/yoyo-524/p/6502827.html

day01_初識python

編譯型&#xff1a;一次性將所有的代碼編譯呈二進制文件。C/C 優點&#xff1a;執行效率高 缺點&#xff1a;開發速度慢&#xff0c;不能跨平臺 解釋型&#xff1a;當程序運行時&#xff0c;從上到下一行一行的解釋為二進制文件 優點&#xff1a;開發效率快&#xff0c;可以跨平…

leetcode1414. 和為 K 的最少斐波那契數字數目(貪心算法)

給你數字 k &#xff0c;請你返回和為 k 的斐波那契數字的最少數目&#xff0c;其中&#xff0c;每個斐波那契數字都可以被使用多次。 斐波那契數字定義為&#xff1a; F1 1 F2 1 Fn Fn-1 Fn-2 &#xff0c; 其中 n > 2 。 數據保證對于給定的 k &#xff0c;一定能找…