欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

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

常量池主要存放兩大類(lèi)常量:字面量;符號(hào)引用

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

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

符號(hào)引用包含三類(lèi)引用:
1、 類(lèi)和接口的全限定名 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è)語(yǔ)句
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)類(lèi)加載到內(nèi)存中后,jvm就會(huì)將class常量池中的內(nèi)容存放到運(yùn)行時(shí)常量池中。 里面放的也是符號(hào)引用和字面量,跟我們的class文件常量池放的東西是一樣的

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

問(wèn)題:Class 文件信息是否能跟方法區(qū)對(duì)應(yīng)上來(lái)?

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

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

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

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

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

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

2.直接引用

直接引用和虛擬機(jī)的布局是相關(guān)的如果有了直接引用,那么直接引用的目標(biāo)一定被加載到了內(nèi)存中。(有具體引用地址的指針,被引用的類(lè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)用方法的符號(hào)引用轉(zhuǎn)換為直接引用的過(guò)程稱之為靜態(tài)鏈接

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

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

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

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

案例分析

有一個(gè)父類(lèi)B 和子類(lèi)B2 ,子類(lèi)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");
    }
}

//只能重寫(xiě)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è)類(lèi),因?yàn)樗@個(gè)方法可以被重寫(xiě)了,他可以是B類(lèi)的getA方法,也可以是B2的get方法。此時(shí)這個(gè) b2.b() 他是靜態(tài)鏈接,他在編譯期就確定是B類(lèi)的b方法,是可以直接引用的

問(wèn)題 :動(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的類(lèi),但是符號(hào)引用是B,是根據(jù)聲明量B來(lái)的
然后動(dòng)態(tài)鏈接會(huì)幫助我們?cè)谟胋2.getB方法的時(shí)候,幫我們指向B2 而不是一開(kāi)始寫(xiě)的B。

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

相關(guān)文章

  • pageHelper一對(duì)多分頁(yè)解決方案示例

    pageHelper一對(duì)多分頁(yè)解決方案示例

    這篇文章主要為大家介紹了pageHelper一對(duì)多分頁(yè)解決方案示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 關(guān)于jvm的垃圾回收器以及觸發(fā)full gc的場(chǎng)景

    關(guān)于jvm的垃圾回收器以及觸發(fā)full gc的場(chǎng)景

    這篇文章主要介紹了關(guān)于jvm的垃圾回收器以及觸發(fā)full gc的場(chǎng)景,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Springboot整合Thymeleaf引入公共的CSS和JS文件的方法及注意點(diǎn)

    Springboot整合Thymeleaf引入公共的CSS和JS文件的方法及注意點(diǎn)

    有時(shí)候很多css文件是公共的,我們必須要在每個(gè)html文件中引入它們,下面這篇文章主要給大家介紹了關(guān)于Springboot整合Thymeleaf引入公共的CSS和JS文件的方法及注意點(diǎn),需要的朋友可以參考下
    2024-06-06
  • springboot整合logback打印日志,分文件

    springboot整合logback打印日志,分文件

    本文主要介紹了springboot整合logback打印日志,分文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11
  • 一文詳解Spring的Enablexxx注解使用實(shí)例

    一文詳解Spring的Enablexxx注解使用實(shí)例

    這篇文章主要為大家介紹了一文詳解Spring的Enablexxx注解使用實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 深入淺析Spring-boot-starter常用依賴模塊

    深入淺析Spring-boot-starter常用依賴模塊

    這篇文章主要介紹了Spring-boot-starter常用依賴模塊及spring boot的兩大優(yōu)點(diǎn),需要的朋友可以參考下
    2018-01-01
  • Java對(duì)象轉(zhuǎn)json的方法過(guò)程解析

    Java對(duì)象轉(zhuǎn)json的方法過(guò)程解析

    這篇文章主要介紹了Java對(duì)象轉(zhuǎn)json的方法過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Spring和SpringMVC掃描注解類(lèi)沖突的解決方案

    Spring和SpringMVC掃描注解類(lèi)沖突的解決方案

    這篇文章主要介紹了Spring和SpringMVC掃描注解類(lèi)沖突的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 解析Java的Spring框架的BeanPostProcessor發(fā)布處理器

    解析Java的Spring框架的BeanPostProcessor發(fā)布處理器

    這篇文章主要介紹了Java的Spring框架的BeanPostProcessor發(fā)布處理器,Spring是Java的SSH三大web開(kāi)發(fā)框架之一,需要的朋友可以參考下
    2015-12-12
  • 詳解JAVA中的Collection接口和其主要實(shí)現(xiàn)的類(lèi)

    詳解JAVA中的Collection接口和其主要實(shí)現(xiàn)的類(lèi)

    這篇文章主要介紹了JAVA中的Collection接口和其主要實(shí)現(xiàn)的類(lèi),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03

最新評(píng)論