0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

JVM入門之Class結(jié)構(gòu)介紹1

jf_78858299 ? 來源:北洋洋洋 ? 作者:北洋 ? 2023-02-09 16:57 ? 次閱讀

Class文件規(guī)范

?根據(jù)《JAVA虛擬機(jī)規(guī)范》的規(guī)定,Class文件格式采用一種類似于C語言結(jié)構(gòu)體的偽結(jié)構(gòu)來存儲(chǔ)數(shù)據(jù),這種偽結(jié)構(gòu)中(Class文件格式中)只有兩種數(shù)據(jù)類型:“無符號(hào)數(shù)”和“表”。

?

?本篇文章圖中貼出的類型這一列也都是這兩個(gè)數(shù)據(jù)類型,如果類型是u開頭的表示為無符號(hào)數(shù)的數(shù)據(jù)類型,如果是_info結(jié)尾的表示是表類型。

?

  1. 無符號(hào)數(shù)就是正常的數(shù)字,以u(píng)1,u2,u4,u8來表示一個(gè),兩個(gè),四個(gè),八個(gè)字節(jié),通常用來描述數(shù)字,索引引用,數(shù)量值或者用來表達(dá)字符串值。

?u1在Class文件中為兩個(gè)數(shù)字或字母,比如00,01,0A,6F ; u2在Class文件中為四個(gè)數(shù)字或字母,比如0001,000A,6C61;

?

  1. 表是用來描述復(fù)合結(jié)構(gòu)的數(shù)據(jù),它由無符號(hào)數(shù)或者其他表構(gòu)成,并在結(jié)尾處用“_info”表示。

?比如:cp_info為常量池表,field_info為字段表,method_info為方法表,attribute_info為屬性表。本篇文章會(huì)講解除了屬性表之外的其他表結(jié)構(gòu),屬性表單獨(dú)寫一篇文章進(jìn)行講解

?

  1. 本質(zhì)上Class結(jié)構(gòu)也是將表和無符號(hào)數(shù)組合起來的一張表。

Class文件大結(jié)構(gòu)總覽

后面講的所有結(jié)構(gòu)都是按照這個(gè)Class文件表講的,所以這張圖先看下。

magic

Class文件的 「頭四個(gè)字節(jié)」 表示魔數(shù),這個(gè)值存在于各個(gè)文件中,在之前的這篇文章里面講過這個(gè)字段:驗(yàn)證apk文件的magic,magic是用來驗(yàn)證是不是屬于某種結(jié)構(gòu)的,即使用戶更改了文件的后綴名也沒事,通過這個(gè)字段就可以看出他是什么類型的文件。「因此每一種文件格式的魔數(shù)magic都不一樣,因?yàn)槭怯脕肀硎酒鋵儆谀姆N文件格式的?!?/strong>

?Class文件的magic為0XCAFFBABE(咖啡寶貝)

?

Class文件版本號(hào)

接下來的兩個(gè)字節(jié)表達(dá)的Class文件的 「次版本號(hào)(Minor Version)」 ,再接著兩個(gè)字節(jié)表達(dá)的是 「主版本號(hào)(Major Version)」 。

?高版本的JDK能夠兼容低版本的Class文件,但是低版本的JDK不能運(yùn)行高版本的Class文件(規(guī)范中Class文件校驗(yàn)必須要求的?。?/p>

?

Constant_Pool常量池

1、Class文件中第一個(gè)出現(xiàn)的表結(jié)構(gòu)的數(shù)據(jù),主要存放兩種常量:「字面量和符號(hào)引用?!?/strong>

?字面量:Java語言層面常量的概念。eg:字符串,被聲明為final的常量等

?

?符號(hào)引用:編譯原理方面的概念。eg:被模塊導(dǎo)出或者開放的包(Package) 類和接口的全限定名(也就是類所屬的包名和類的名字) 字段的名稱和描述符(名稱簡(jiǎn)單理解就是字段名,描述符為字段所屬的類型) 方法的名稱和描述符(名稱簡(jiǎn)單理解就是方法名,描述符為方法參數(shù)和返回值) 方法句柄和方法類型(Method Handle,Method Type,Invoke Dynamic) 動(dòng)態(tài)調(diào)用點(diǎn)和動(dòng)態(tài)常量

?

2、符號(hào)引用,由于Class文件是在編譯后生成的,因此運(yùn)行的時(shí)候需要 「將符號(hào)引用轉(zhuǎn)換為對(duì)應(yīng)數(shù)據(jù)在內(nèi)存中的地址」 ,否則使用的時(shí)候會(huì)找不到真正的內(nèi)存入口地址(也就是不能被虛擬機(jī)直接使用)。

?當(dāng)虛擬機(jī)做類加載的時(shí)候,會(huì)從常量池中拿出對(duì)應(yīng)的符號(hào)引用,在類創(chuàng)建或者運(yùn)行時(shí)解析,翻譯到具體的內(nèi)存地址之中 比如class文件的類名,當(dāng)類被加載到虛擬機(jī)中時(shí),需要將這個(gè)符號(hào)引用轉(zhuǎn)換為類真實(shí)所在的內(nèi)存地址才能被正常訪問。

?

3.常量池中存儲(chǔ)的數(shù)據(jù)數(shù)量 「從1開始計(jì)數(shù)」 ,第0項(xiàng)常量空出來是因?yàn)橛行?shù)據(jù)并不需要引用常量池中的數(shù)據(jù)時(shí),就可以用第0項(xiàng)常量來表達(dá)。

4.常量池的數(shù)據(jù)數(shù)量會(huì)在版本號(hào)之后用兩個(gè)字節(jié)來表達(dá),之后才是常量池中的數(shù)據(jù)

?這樣做是因?yàn)闆]有Class文件中 「沒有分隔符」 來表示一組數(shù)據(jù)結(jié)束,因此Class文件中的數(shù)據(jù)必須嚴(yán)格按照固定長(zhǎng)度,固定數(shù)量去存放,不允許改變。

?

5.常量池中 「每一項(xiàng)常量數(shù)據(jù)都是一張表」 ,每個(gè)表結(jié)構(gòu)中都有一個(gè)u1類型的標(biāo)志位標(biāo)識(shí)自己屬于哪種類型的表。

各個(gè)表對(duì)應(yīng)的含義

這些表有著各自完全獨(dú)立的結(jié)構(gòu),之間沒有任何關(guān)聯(lián)。

反編譯代碼示例

C:\\>javap -verbose TestClass 
Compiled from "TestClass.java" 
public class org.fenixsoft.clazz.TestClass extends java.lang.Object     SourceFile: "TestClass.java"     
minor version: 0     
major version: 50     
Constant pool: 
const #1 = class        #2;     //  org/fenixsoft/clazz/TestClass 
const #2 = Asciz        org/fenixsoft/clazz/TestClass; 
const #3 = class        #4;     //  java/lang/Object 
const #4 = Asciz        java/lang/Object; 
const #5 = Asciz        m; 
const #6 = Asciz        I; 
const #7 = Asciz        ; 
const #8 = Asciz        ()V; 
const #9 = Asciz        Code; 
const #10 = Method      #3.#11; //  java/lang/Object."":()V 
const #11 = NameAndType #7:#8;//  "":()V 
const #12 = Asciz       LineNumberTable; 
const #13 = Asciz       LocalVariableTable; 
const #14 = Asciz       this; 
const #15 = Asciz       Lorg/fenixsoft/clazz/TestClass;; 
const #16 = Asciz       inc; 
const #17 = Asciz       ()I; 
const #18 = Field       #1.#19; // org/fenixsoft/clazz/TestClass.m:I 
const #19 = NameAndType #5:#6;  // m:I 
const #20 = Asciz       SourceFile; 
const #21 = Asciz       TestClass.java;

代碼塊中Asciz就是之前說的Constant_UTF8_info常量(也就是字符串常量),可以看到這些數(shù)據(jù)都是由這個(gè)常量來組成的,

常量池中常量表對(duì)應(yīng)數(shù)據(jù)結(jié)構(gòu)內(nèi)容

第一列常量為之前 「各個(gè)表對(duì)應(yīng)的含義」 中提到的表結(jié)構(gòu)類型也就是表的名稱;

第二列中的項(xiàng)目為各個(gè)表中存放的不同的數(shù)據(jù)內(nèi)容有哪些,這些表的數(shù)據(jù)中都有一個(gè)標(biāo)識(shí)位tag用來標(biāo)識(shí)不同的表,在之前 「各個(gè)表對(duì)應(yīng)的含義」 中也提到過;

第三列為描述不同于之前講的表的描述,這列說明的是**「表中存儲(chǔ)的不同數(shù)據(jù)的描述」**

圖例:

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2943

    瀏覽量

    104110
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7575

    瀏覽量

    134157
  • Class
    +關(guān)注

    關(guān)注

    0

    文章

    52

    瀏覽量

    19676
  • 存儲(chǔ)數(shù)據(jù)

    關(guān)注

    0

    文章

    83

    瀏覽量

    14060
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    jvm的類加載器的整體結(jié)構(gòu)及過程解析

    前言 我們很多小伙伴平時(shí)都是做JAVA開發(fā)的,那么作為一名合格的工程師,你是否有仔細(xì)的思考過JVM的運(yùn)行原理呢。 如果懂得了JVM的運(yùn)行原理和內(nèi)存模型,像是一些JVM調(diào)優(yōu)、垃圾回收機(jī)制等等的問題我們
    的頭像 發(fā)表于 09-27 15:49 ?3333次閱讀
    <b class='flag-5'>jvm</b>的類加載器的整體<b class='flag-5'>結(jié)構(gòu)</b>及過程解析

    Proteus基礎(chǔ)入門教程 Proteus界面功能介紹及常用操作

    Proteus基礎(chǔ)入門教程 Proteus界面功能介紹及常用操作
    發(fā)表于 09-27 22:35

    Jvm的整體結(jié)構(gòu)和特點(diǎn)

    的整體結(jié)構(gòu)大致如下:    1、類加載器  類加載器用來加載Java類到JVM虛擬機(jī)中,源代碼程序.java文件在經(jīng)過編譯器編譯之后就被轉(zhuǎn)換成字節(jié)代碼.class文件,類加載器負(fù)責(zé)讀取
    發(fā)表于 01-05 17:23

    Jvm工作原理學(xué)習(xí)筆記

    [] args)函數(shù)的class都可以作為JVM實(shí)例運(yùn)行的起點(diǎn) b) 運(yùn)行。main()作為該程序初始線程的起點(diǎn),任何其他線程均由該線程啟動(dòng)。JVM內(nèi)部有兩種線程:守護(hù)線程和非守護(hù)線程,main()屬于非守護(hù)
    發(fā)表于 04-03 11:03 ?5次下載

    Java:JVM虛擬機(jī)的入門知識(shí)

    Java開發(fā)現(xiàn)在面試越來越難了,進(jìn)大廠必備的JVM、多線程高并發(fā)這都是最基礎(chǔ)的知識(shí)了,今天我們一起來學(xué)習(xí)Java虛擬機(jī)入門。
    的頭像 發(fā)表于 07-01 11:43 ?2229次閱讀
    Java:<b class='flag-5'>JVM</b>虛擬機(jī)的<b class='flag-5'>入門</b>知識(shí)

    UM1802_STM32CubeL1入門STM32L1系列

    UM1802_STM32CubeL1入門STM32L1系列
    發(fā)表于 11-22 08:22 ?1次下載
    UM1802_STM32CubeL<b class='flag-5'>1</b><b class='flag-5'>入門</b><b class='flag-5'>之</b>STM32L<b class='flag-5'>1</b>系列

    JVM入門Class結(jié)構(gòu)介紹2

    本篇文章圖中貼出的類型這一列也都是這兩個(gè)數(shù)據(jù)類型,如果類型是u開頭的表示為無符號(hào)數(shù)的數(shù)據(jù)類型,如果是_info結(jié)尾的表示是表類型。
    的頭像 發(fā)表于 02-09 16:57 ?407次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>入門</b><b class='flag-5'>之</b><b class='flag-5'>Class</b><b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>介紹</b>2

    JVM入門Class結(jié)構(gòu)屬性表1

    ?屬性表在《JAVA虛擬機(jī)規(guī)范》中并沒有像其他數(shù)據(jù)一樣做嚴(yán)格的限制,我們甚至可以自己實(shí)現(xiàn)一個(gè)編譯器往Class結(jié)構(gòu)的屬性表中注入額外的屬性信息,虛擬機(jī)運(yùn)行時(shí)會(huì)忽略掉它識(shí)別不了的屬性。
    的頭像 發(fā)表于 02-10 11:02 ?486次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>入門</b><b class='flag-5'>之</b><b class='flag-5'>Class</b><b class='flag-5'>結(jié)構(gòu)</b>屬性表<b class='flag-5'>1</b>

    JVM入門Class結(jié)構(gòu)屬性表2

    ?屬性表在《JAVA虛擬機(jī)規(guī)范》中并沒有像其他數(shù)據(jù)一樣做嚴(yán)格的限制,我們甚至可以自己實(shí)現(xiàn)一個(gè)編譯器往Class結(jié)構(gòu)的屬性表中注入額外的屬性信息,虛擬機(jī)運(yùn)行時(shí)會(huì)忽略掉它識(shí)別不了的屬性。
    的頭像 發(fā)表于 02-10 11:02 ?468次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>入門</b><b class='flag-5'>之</b><b class='flag-5'>Class</b><b class='flag-5'>結(jié)構(gòu)</b>屬性表2

    JVM入門認(rèn)識(shí)程序運(yùn)行本質(zhì)

    寫JAVA文件然后用javac命令編譯成class文件運(yùn)行即可。 > > ? 隨著學(xué)習(xí)的不斷拓展和工作中業(yè)務(wù)代碼的積累,對(duì)于“為什么會(huì)這樣”的困惑越來越多,于是寫了這篇博客
    的頭像 發(fā)表于 02-10 11:48 ?570次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>入門</b><b class='flag-5'>之</b>認(rèn)識(shí)程序運(yùn)行本質(zhì)

    USB Class介紹

    電子發(fā)燒友網(wǎng)站提供《USB Class介紹.pdf》資料免費(fèi)下載
    發(fā)表于 08-01 16:19 ?0次下載
    USB <b class='flag-5'>Class</b>的<b class='flag-5'>介紹</b>

    垃圾收集器的JVM參數(shù)配置

    效率,那么進(jìn)行相關(guān)的JVM參數(shù)設(shè)置是必不可少的。下面我們就來對(duì)這些JVM參數(shù)進(jìn)行詳細(xì)的介紹。JVM參數(shù)主要分為以下三種(可以根據(jù)書寫形式來區(qū)分):
    的頭像 發(fā)表于 10-09 16:35 ?461次閱讀
    垃圾收集器的<b class='flag-5'>JVM</b>參數(shù)配置

    jvm內(nèi)存溢出該如何定位解決

    超出限制和堆空間不足。 定位JVM內(nèi)存溢出問題是一個(gè)比較復(fù)雜的任務(wù),需要結(jié)合工具和技術(shù)來進(jìn)行分析和解決。本文將介紹一些常用的調(diào)試和解決內(nèi)存溢出問題的工具和技術(shù)。 一、理解JVM內(nèi)存結(jié)構(gòu)
    的頭像 發(fā)表于 12-05 11:05 ?1133次閱讀

    jvm內(nèi)存模型和內(nèi)存結(jié)構(gòu)

    JVM(Java虛擬機(jī))是Java程序的運(yùn)行平臺(tái),它負(fù)責(zé)將Java程序轉(zhuǎn)換成機(jī)器碼并在計(jì)算機(jī)上執(zhí)行。在JVM中,內(nèi)存模型和內(nèi)存結(jié)構(gòu)是兩個(gè)重要的概念,本文將詳細(xì)介紹它們。 一、
    的頭像 發(fā)表于 12-05 11:08 ?736次閱讀

    jvm參數(shù)的設(shè)置和jvm調(diào)優(yōu)

    JVM(Java虛擬機(jī))參數(shù)的設(shè)置和調(diào)優(yōu)對(duì)于提高Java應(yīng)用程序的性能和穩(wěn)定性非常重要。在本文中,我們將詳細(xì)介紹JVM參數(shù)的設(shè)置和調(diào)優(yōu)方法。 一、JVM參數(shù)的設(shè)置 內(nèi)存參數(shù): -Xms
    的頭像 發(fā)表于 12-05 11:36 ?1048次閱讀