最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?常量池詳解之class文件常量池?和class運(yùn)行時(shí)常量池

 更新時(shí)間:2022年12月27日 10:28:55   作者:new?hilbert()  
這篇文章主要介紹了Java?常量池詳解之class文件常量池?和class運(yùn)行時(shí)常量池,常量池主要存放兩大類常量:字面量,符號引用,本文結(jié)合示例代碼對java class常量池相關(guān)知識(shí)介紹的非常詳細(xì),需要的朋友可以參考下

Java 常量池詳解(一)字符串常量池

2.class文件常量池(class constant pool)

產(chǎn)生時(shí)機(jī):當(dāng)java文件被編譯成class文件之后,就會(huì)生成class常量池,跟jvm 無關(guān)系

常量池主要存放兩大類常量:字面量;符號引用

字面量接近Java語言層面的常量概念,如文本字符串、聲明為final的常量值等

(Integer、 Float 、Long、 Double、 String、 UTF-8)

符號引用包含三類引用:
1、 類和接口的全限定名 org.springframework…Bean
舉例:jvm/Hotspot/ConstantsTest

 #7 = Class              #41            // jvm/Hotspot/ConstantsTest
 #41 = Utf8               jvm/Hotspot/ConstantsTest

2、字段的名稱和描述符
舉例: int b

 #4 = Fieldref           #7.#37         // jvm/Hotspot/ConstantsTest.b:I
 #7 = Class              #41            // jvm/Hotspot/ConstantsTest
 #37 = NameAndType        #17:#18        // b:I
 #41 = Utf8               jvm/Hotspot/ConstantsTest
 #17 = Utf8               b
 #18 = Utf8               I

3、方法的名稱和描述符
舉例:int getB()

 #9 = Methodref          #7.#42          // jvm/Hotspot/ConstantsTest.getB:()I
 #7 = Class              #41            // jvm/Hotspot/ConstantsTest
 #42 = NameAndType        #26:#27        // getB:()I 
 #41 = Utf8               jvm/Hotspot/ConstantsTest
 #26 = Utf8               getB
 #27 = Utf8               ()I

Class 文件布局 如下(跟方法區(qū)布局息息相關(guān)的)

public class ConstantsTest {
    private static Integer a = 10;
    private int b;
    private String c = "cc";
    private static String d = "dd";

    public int getB() {
        return b;
    }

    public static int getA() {
        return a;
    }

    public static void main(String[] args) {
        ConstantsTest constantsTest = new ConstantsTest();
        constantsTest.getB();
        ConstantsTest.getA();
    }
}

//執(zhí)行下面這個(gè)語句
javap -c -v -p ConstantsTest.class 得到

public class jvm.Hotspot.ConstantsTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #14.#34        // java/lang/Object."<init>":()V
   #2 = String             #35            // cc
   #3 = Fieldref           #7.#36         // jvm/Hotspot/ConstantsTest.c:Ljava/lang/String;
   #4 = Fieldref           #7.#37         // jvm/Hotspot/ConstantsTest.b:I
   #5 = Fieldref           #7.#38         // jvm/Hotspot/ConstantsTest.a:Ljava/lang/Integer;
   #6 = Methodref          #39.#40        // java/lang/Integer.intValue:()I
   #7 = Class              #41            // jvm/Hotspot/ConstantsTest
   #8 = Methodref          #7.#34         // jvm/Hotspot/ConstantsTest."<init>":()V
   #9 = Methodref          #7.#42         // jvm/Hotspot/ConstantsTest.getB:()I
  #10 = Methodref          #7.#43         // jvm/Hotspot/ConstantsTest.getA:()I
  #11 = Methodref          #39.#44        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
  #12 = String             #45            // dd
  #13 = Fieldref           #7.#46         // jvm/Hotspot/ConstantsTest.d:Ljava/lang/String;
  #14 = Class              #47            // java/lang/Object
  #15 = Utf8               a
  #16 = Utf8               Ljava/lang/Integer;
  #17 = Utf8               b
  #18 = Utf8               I
  #19 = Utf8               c
  #20 = Utf8               Ljava/lang/String;
  #21 = Utf8               d
  #22 = Utf8               <init>
  #23 = Utf8               ()V
  #24 = Utf8               Code
  #25 = Utf8               LineNumberTable
  #26 = Utf8               getB
  #27 = Utf8               ()I
  #28 = Utf8               getA
  #29 = Utf8               main
  #30 = Utf8               ([Ljava/lang/String;)V
  #31 = Utf8               <clinit>
  #32 = Utf8               SourceFile
  #33 = Utf8               ConstantsTest.java
  #34 = NameAndType        #22:#23        // "<init>":()V
  #35 = Utf8               cc
  #36 = NameAndType        #19:#20        // c:Ljava/lang/String;
  #37 = NameAndType        #17:#18        // b:I
  #38 = NameAndType        #15:#16        // a:Ljava/lang/Integer;
  #39 = Class              #48            // java/lang/Integer
  #40 = NameAndType        #49:#27        // intValue:()I
  #41 = Utf8               jvm/Hotspot/ConstantsTest
  #42 = NameAndType        #26:#27        // getB:()I
  #43 = NameAndType        #28:#27        // getA:()I
  #44 = NameAndType        #50:#51        // valueOf:(I)Ljava/lang/Integer;
  #45 = Utf8               dd
  #46 = NameAndType        #21:#20        // d:Ljava/lang/String;
  #47 = Utf8               java/lang/Object
  #48 = Utf8               java/lang/Integer
  #49 = Utf8               intValue
  #50 = Utf8               valueOf
  #51 = Utf8               (I)Ljava/lang/Integer;
{
  private static java.lang.Integer a;
    descriptor: Ljava/lang/Integer;
    flags: ACC_PRIVATE, ACC_STATIC

  private int b;
    descriptor: I
    flags: ACC_PRIVATE

  private java.lang.String c;
    descriptor: Ljava/lang/String;
    flags: ACC_PRIVATE

  private static java.lang.String d;
    descriptor: Ljava/lang/String;
    flags: ACC_PRIVATE, ACC_STATIC

  public jvm.Hotspot.ConstantsTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String cc
         7: putfield      #3                  // Field c:Ljava/lang/String;
        10: return
      LineNumberTable:
        line 10: 0
        line 13: 4

  public int getB();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #4                  // Field b:I
         4: ireturn
      LineNumberTable:
        line 17: 0

  public static int getA();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: getstatic     #5                  // Field a:Ljava/lang/Integer;
         3: invokevirtual #6                  // Method java/lang/Integer.intValue:()I
         6: ireturn
      LineNumberTable:
        line 21: 0

  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 jvm/Hotspot/ConstantsTest
         3: dup
         4: invokespecial #8                  // Method "<init>":()V
         7: astore_1
         8: aload_1
         9: invokevirtual #9                  // Method getB:()I
        12: pop
        13: invokestatic  #10                 // Method getA:()I
        16: pop
        17: return
      LineNumberTable:
        line 25: 0
        line 26: 8
        line 27: 13
        line 28: 17

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: bipush        10
         2: invokestatic  #11                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         5: putstatic     #5                  // Field a:Ljava/lang/Integer;
         8: ldc           #12                 // String dd
        10: putstatic     #13                 // Field d:Ljava/lang/String;
        13: return
      LineNumberTable:
        line 11: 0
        line 14: 8
}

3.class運(yùn)行時(shí)常量池

Class運(yùn)行時(shí)常量池其實(shí)是當(dāng)類加載到內(nèi)存中后,jvm就會(huì)將class常量池中的內(nèi)容存放到運(yùn)行時(shí)常量池中。 里面放的也是符號引用和字面量,跟我們的class文件常量池放的東西是一樣的

可以把Class文件常量池看作靜態(tài)常量池(里面是符號引用), 而運(yùn)行時(shí)常量池是動(dòng)態(tài)常量池(里面有直接引用),他倆是同一個(gè)東西,只是狀態(tài)時(shí)機(jī)不同而已。

問題:Class 文件信息是否能跟方法區(qū)對應(yīng)上來?

發(fā)現(xiàn)是能跟夠一一對應(yīng)的上的。方法區(qū)其實(shí)就可以簡單看成運(yùn)行狀態(tài)的Class文件的布局

1. 符號引用(脫離jvm 體系來講,就單純class文件的符號引用而已)

符號引用以一組符號來描述所引用的目標(biāo),在編譯的時(shí)候一個(gè)每個(gè)java類都會(huì)被編譯成一個(gè)class文件, 但在編譯的時(shí)候虛擬機(jī)并不知道所引用類的地址,多以就用符號引用來代替 ,而在這個(gè)解析階段就是為了把這個(gè)符號引用轉(zhuǎn)化成為真正的地址的階段

比如:class 文件里面有個(gè)方法調(diào)用getB()方法。 還沒到準(zhǔn)備階段(虛擬機(jī)就會(huì)進(jìn)入準(zhǔn)備階段。在這個(gè)階段,虛擬機(jī)就會(huì)為這個(gè)類分配相應(yīng)的內(nèi)存空間,并設(shè)置默認(rèn)初始值)。是不知道具體new 對象所在的地址的。class 文件里面只是符號引用,知道是用這個(gè)類的方法。

 public static void main(String[] args) {
        ConstantsTest constantsTest = new ConstantsTest();
        constantsTest.getB();
}
//對應(yīng)的反編譯 代碼其實(shí) 是
9: invokevirtual #9                  // Method getB:()I

但其實(shí)#9 是常量池里面的 // jvm/Hotspot/ConstantsTest.getB:()I

2.直接引用

直接引用和虛擬機(jī)的布局是相關(guān)的如果有了直接引用,那么直接引用的目標(biāo)一定被加載到了內(nèi)存中。(有具體引用地址的指針,被引用的類、方法或者變量已經(jīng)被加載到內(nèi)存中)

3.靜態(tài)鏈接

當(dāng)一個(gè)字節(jié)碼文件被裝載進(jìn) JVM 內(nèi)部時(shí),如果被調(diào)用的目標(biāo)方法在編譯期可知,且運(yùn)行期保持不變時(shí),這種情況下將調(diào)用方法的符號引用轉(zhuǎn)換為直接引用的過程稱之為靜態(tài)鏈接

比如:調(diào)用靜態(tài)方法, 調(diào)用實(shí)例的私有構(gòu)造器, 私有方法, 父類方法,被final修飾的方法(其實(shí)就是不能被子類重寫的方法,能確定唯一性)

4.動(dòng)態(tài)鏈接

如果被調(diào)用的方法在編譯期無法被確定下來,也就是說,只能夠在程序運(yùn)行期將調(diào)用的方法的符號轉(zhuǎn)換為直接引用,由于這種引用轉(zhuǎn)換過程具備動(dòng)態(tài)性,因此也被稱之為動(dòng)態(tài)鏈接。

比如:(B b = new B2() ) 父類聲明,子類實(shí)現(xiàn)的情況,方法被子類重寫了。

案例分析

有一個(gè)父類B 和子類B2 ,子類B2實(shí)現(xiàn)了B的getA 方法

public class B {
    private int a = 2;

    public int getA() {
        return a;
    }

    public static void print() {
        System.out.println("aaa");
    }

    public final void b() {

    }

    private void c() {
        System.out.println("c");
    }
}

//只能重寫getA方法
public class B2 extends B {
    @Override
    public int getA() {
        return 2;
}   

此時(shí)有個(gè)線程調(diào)用了聲明為B ,但是實(shí)現(xiàn)為B2的方法

public static void main(String[] args) {
    B b2 = new B2();
    b2.getA();
    b2.b();
}

class文件編譯結(jié)果如下:

0: new           #4                  // class jvm/Hotspot/B2
3: dup
4: invokespecial #5                  // Method jvm/Hotspot/B2."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #2                  // Method jvm/Hotspot/B.getA:()I
12: pop
13: aload_1
14: invokevirtual #6                  // Method jvm/Hotspot/B.b:()V
17: return

此時(shí)這個(gè) b2.getA() 他是動(dòng)態(tài)鏈接,他只有在運(yùn)行期間才知道用了具體哪個(gè)類,因?yàn)樗@個(gè)方法可以被重寫了,他可以是B類的getA方法,也可以是B2的get方法。此時(shí)這個(gè) b2.b() 他是靜態(tài)鏈接,他在編譯期就確定是B類的b方法,是可以直接引用的

問題 :動(dòng)態(tài)鏈接跟什么有關(guān)系?

動(dòng)態(tài)鏈接在棧幀里面,不會(huì)在停留在方法區(qū)里面,是跟線程有關(guān)系的

public class A {
    int a = 1;
    public int getA() {
        return a;
    }
}

public class A2 extends A {
    @Override
    public int getA() {
        return 10;
    }
}

public class B {
    public int getB(A a) {
        return a.getA();
    }
}

public class B2 extends B {
    @Override
    public int getB(A a) {
        return a.getA()+1;
    }
}

線程調(diào)用

public static void main(String[] args) {
        B b2 = new B2();
        A a2 = new A2();
        b2.getB(a2);
}

//java反編譯之后得到
0: new           #2                  // class jvm/Hotspot/B2
3: dup
4: invokespecial #3                  // Method jvm/Hotspot/B2."<init>":()V
7: astore_1
8: new           #4                  // class jvm/Hotspot/A2
11: dup
12: invokespecial #5                  // Method jvm/Hotspot/A2."<init>":()V
15: astore_2
16: aload_1
17: aload_2
18: invokevirtual #6          // Method jvm/Hotspot/B.getB:(Ljvm/Hotspot/A;)I
21: pop
22: return

雖然我們初始化的是B2的類,但是符號引用是B,是根據(jù)聲明量B來的
然后動(dòng)態(tài)鏈接會(huì)幫助我們在用b2.getB方法的時(shí)候,幫我們指向B2 而不是一開始寫的B。

到此這篇關(guān)于Java 常量池詳解之class文件常量池 和class運(yùn)行時(shí)常量池的文章就介紹到這了,更多相關(guān)Java class常量池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Lambda表達(dá)式的使用及注意事項(xiàng)

    Lambda表達(dá)式的使用及注意事項(xiàng)

    這篇文章主要介紹了Lambda表達(dá)式的使用及注意事項(xiàng),主要圍繞?Lambda表達(dá)式的省略模式?Lambda表達(dá)式和匿名內(nèi)部類的區(qū)別的相關(guān)內(nèi)容展開詳情,感興趣的小伙伴可以參考一下
    2022-06-06
  • java如何根據(jù)模板導(dǎo)出數(shù)據(jù)到word文檔中(表格、自定義標(biāo)簽等)

    java如何根據(jù)模板導(dǎo)出數(shù)據(jù)到word文檔中(表格、自定義標(biāo)簽等)

    這篇文章主要介紹了關(guān)于java如何根據(jù)模板導(dǎo)出數(shù)據(jù)到word文檔中(表格、自定義標(biāo)簽等)的相關(guān)資料,主要包括創(chuàng)建docx文檔,配置模板信息,以及利用XDocReport+FreeMarker技術(shù)進(jìn)行實(shí)現(xiàn),詳細(xì)介紹了在Word模板中如何設(shè)置字段以及如何通過代碼填充這些字段,需要的朋友可以參考下
    2024-11-11
  • Servlet系列兩種創(chuàng)建方式

    Servlet系列兩種創(chuàng)建方式

    本文主要介紹了Servlet系列兩種創(chuàng)建方式,包含Servlet2.5之前使用和Servlet3.0后,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • 如何把本地jar包導(dǎo)入maven并pom添加依賴

    如何把本地jar包導(dǎo)入maven并pom添加依賴

    這篇文章主要介紹了如何把本地jar包導(dǎo)入maven并pom添加依賴,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • SpringBoot請求發(fā)送與信息響應(yīng)匹配實(shí)現(xiàn)方法介紹

    SpringBoot請求發(fā)送與信息響應(yīng)匹配實(shí)現(xiàn)方法介紹

    這篇文章主要介紹了SpringBoot請求發(fā)送與信息響應(yīng)匹配實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • 淺析Java中對象的創(chuàng)建與對象的數(shù)據(jù)類型轉(zhuǎn)換

    淺析Java中對象的創(chuàng)建與對象的數(shù)據(jù)類型轉(zhuǎn)換

    這篇文章主要介紹了Java中對象的創(chuàng)建與對象的數(shù)據(jù)類型轉(zhuǎn)換,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-01-01
  • SpringBoot使用 druid 連接池來優(yōu)化分頁語句

    SpringBoot使用 druid 連接池來優(yōu)化分頁語句

    這篇文章主要介紹了SpringBoot使用 druid 連接池來優(yōu)化分頁語句,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • JUC并發(fā)編程LinkedBlockingQueue隊(duì)列深入分析源碼

    JUC并發(fā)編程LinkedBlockingQueue隊(duì)列深入分析源碼

    LinkedBlockingQueue 是一個(gè)可選有界阻塞隊(duì)列,這篇文章主要為大家詳細(xì)介紹了Java中LinkedBlockingQueue的實(shí)現(xiàn)原理與適用場景,感興趣的可以了解一下
    2023-04-04
  • Java中的集合工具類Collections詳解

    Java中的集合工具類Collections詳解

    這篇文章主要介紹了Java中的集合工具類Collections詳解,java.utils.Collections是集合工具類,用來對集合進(jìn)行操作,不是Collection集合的根接口,這個(gè)要區(qū)分開來,需要的朋友可以參考下
    2024-01-01
  • IntelliJ IDEA中新建Java class的解決方案

    IntelliJ IDEA中新建Java class的解決方案

    今天小編就為大家分享一篇關(guān)于IntelliJ IDEA中新建Java class的解決方案,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-10-10

最新評論

渭南市| 海晏县| 山东省| 会宁县| 石河子市| 龙游县| 山阴县| 庆云县| 鄯善县| 昌宁县| 宜春市| 托克托县| 进贤县| 潼南县| 阿克苏市| 广河县| 湘阴县| 云浮市| 保山市| 香港| 江都市| 常山县| 罗甸县| 唐河县| 陕西省| 车致| 五华县| 通化市| 无棣县| 庄河市| 吉林省| 安庆市| 齐齐哈尔市| 马公市| 济南市| 鲁山县| 麻江县| 商南县| 二连浩特市| 湘潭市| 淄博市|